繁体   English   中英

在 mousedown 和 mouseup 事件之后防止单击事件

[英]Prevent click event after mousedown & mouseup event

在刚刚触发 mousedown 和 mouseup 事件之后,jQuery 是否可以防止执行同一元素上的单击事件。

任何帮助/示例将不胜感激。

有一种尴尬的方法是在鼠标按下时禁用按钮,并在短时间内启用它,比如 100 毫秒。 如果 mouseup 在此期间发生,则不会触发 click。

 $('#btn').on('click', function() { alert('clicked') }); $('#btn').on('mousedown', function() { var btn = $(this); btn.attr('disabled', 'disabled'); setTimeout(function() { btn.removeAttr('disabled'); }, 100); });
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <body> <button id='btn'>Click me</button> </body>

在 Chrome 和 Internet Explorer 中,而不是 Firefox,在 mousedown 或 mouseup 处分离和重新附加元素将阻止触发单击事件。 在 Internet Explorer 中,这个技巧不会捕获双击(在 Chrome 中它会)。

但我不会依赖这种奇怪的行为,谁知道它是否会在某个时候改变。 此外,请注意分离和重新附加也会对分离元素的子元素产生副作用(iframe 重新加载,文件字段重置,...)。

有一个解决方案:

 const COORDS = { xDown: null, xUp: null } const handleOnMouseDown = e => { e.preventDefault() COORDS.xUp = null COORDS.xDown = e.clientX } const handleMouseUp = e => { e.preventDefault() COORDS.xUp = e.clientX } const handleOnClick = e => { if (COORDS.xDown !== COORDS.xUp) { e.preventDefault() console.log('drag') } else { console.log('click') } } const el = document.getElementById('test') el.addEventListener('mousedown', handleOnMouseDown) el.addEventListener('mouseup', handleMouseUp) el.addEventListener('click', handleOnClick)
 #test { padding: 20px; display: block; background: #ccc }
 <a href="#" id="test">Link</a>

似乎还没有人回答过这个问题,至少不是以一种优雅的方式,所以我想我会分享我发现的 NewbeDev 的解决方案(来源: https ://newbedev.com/cancel-click-event-in- 鼠标事件处理程序

答案是使用捕获阶段,因此在您的元素上触发事件之前,它的所有父级都会在所谓的“捕获阶段”期间收到它。 然后在所谓的“冒泡阶段”中,事件被传递给您的元素,然后是其父元素。

这里的解决方案是在捕获阶段取消顶部的事件,这样它就永远不会在冒泡阶段到达您的元素。

我的用例是一个滑块,所以我使用的代码是这样的:

slider.addEventListener('mousedown', ev => {
    // we start sliding (details omitted)

    function captureClick(e) {
        // we cancel the event and stop it from going further.
        // preventDefault() on its own should be enough for most cases
        // Your handler can also check e.defaultPrevented to know if preventDefault() was called
        e.preventDefault();
        // e.stopPropagation();
    }

   window.addEventListener('click', captureClick, true);
   document.addEventListener('mouseup', e => {
       // cleanup - we wait an extra frame to remove our capture 
       //           in case the click event is delayed
       requestAnimationFrame(() => {
           window.removeEventListener('click', captureClick, true);
       });
   });
});

是的,如果你return false; 在 mouseup 处理程序中,因为在 mousedown 和 mouseup 发生后会触发 onclick。 这在常规 javascript 中是可能的,因此它也应该与 jquery 事件处理程序一起使用。

编辑:

从事件处理程序返回一个布尔值实际上应该足以用于事件消费。 但是,由于这在浏览器中非常不稳定,您应该使用该功能来手动取消事件冒泡:

event.stopPropagation();

其中 event 是您的事件处理程序接收的参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM