为什么鼠标松开事件无法阻止点击事件?

25

jsfiddle

<div class='wrapper'>
    <button class='child'>Click me</button>
</div>

function h(e) {
    e.preventDefault();
    e.stopPropagation();
    e.stopImmediatePropagation();
    alert(e.type);
    return false;
}

document.querySelector('.wrapper').addEventListener('mouseup', h, false);
document.querySelector('.child').addEventListener('click', h, false);

我本来期望这个方法可以防止触发'click'事件,但实际上并没有。然而,将mouseup更改为mousedown确实可以阻止点击事件的发生。

我还尝试将useCapture参数设置为true,但是这也不能产生mouseup的期望行为。我在Chrome和Firefox上进行了测试。在提交错误之前,我想在这里询问一下。

这是当前浏览器的一个bug,还是已经记录的行为?

我已经查阅了W3C标准(DOM level 2),但我没有找到任何可以解释这种行为的东西,但是我可能错过了什么。

在我的特定情况下,我正在尝试让两个监听同一元素事件的代码片段解耦,我认为在具有优先级的部分中使用捕获事件将是解决此问题的最优雅方式,但是我遇到了这个问题。值得一提的是,我只需要支持官方支持的版本的FF和Chrome(包括FF的ESR)。


这里不需要使用 preventDefaultstopImmediatePropagation(顺便说一下),因为没有 <form>,所以不会通过按钮提交,也没有相同类型的多个事件。我认为这是预期的行为,因为 mouseupclick 之前触发,所以 .childmouseup 事件会在其 click 事件之前触发(并冒泡),尽管你已经停止了它,但这并不重要。 - Ian
@Ian - 我添加了这些内容,以确保我不会收到像“你尝试过x()或y()吗?”这样的评论。至于您的其他评论,将useCapture设置为true会强制.wrapper的mouseup在子元素冒泡之前发生。我没有包含此代码,因为无论哪种情况,我都应该只收到一个alert()(具有不同的起源元素),对吧? - beatgammit
如果您想要防止鼠标点击,请使用这个链接:http://jsfiddle.net/zhAHt/9/ - uSeRnAmEhAhAhAhAhA
@user2645707 - 那并没有防止任何事情。那只是在 alert() 之前返回,这不是我想要的...如果我真的想使用它,我必须使用一个全局变量... - beatgammit
3个回答

2

查看这篇 quirksmode 文章

click 事件:

当鼠标在同一元素上按下并释放时触发。

因此,当鼠标单击被释放时,同时会触发 mouseupclick 事件,click 不会等待 mouseup 回调函数执行完毕。几乎总是可以将 mouseupclick 视为同义词。

为了取消 click,就像您演示的那样,可以在 mousedown 事件回调函数中返回 false,这样可以防止 click 事件完成。


25
那是不正确的,返回false,或者 event.preventPropagation 可以阻止 mouseup 事件但无法阻止 click 事件。 - eveevans
@eveevans 我认为你错了。在mousedown上这样做似乎会阻止mouseup和click事件的触发。看看我的答案...(我在chrome上测试过) - Tiago Coelho
4
刚刚尝试了一下,但它不起作用。 - Eric Jorgensen

0

终于找到了一种防止点击事件触发的方法。在最新版本的Chromium和Firefox上进行了测试。这可能是某些错误或实现细节。

解决方案

处理onpointerdownonpointerup事件,删除元素并将其插入相同的位置。

<span>
    <button onpointerdown="let parent = this.parentElement; this.remove(); parent.appendChild(this);" onclick="alert();">TEST</button>
</span>

结果

onpointerdown
onmousedown
onpointerup
onmouseup
<-- no click event occures

0

我只是想提供我的解决方案:

let click_works = true
this.addEventListener('mousedown', e => {
    click_works = // condition why the click may work or not
})
this.addEventListener('click', e => {
    if (click_works) // Do your stuff
})

希望这能帮助到某个人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接