取消mouseup事件处理程序中的单击事件

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (75)

在编写一些拖放代码时,我想取消mouseup处理程序中的单击事件。我认为,防止默认应该可以发挥作用,但单击事件仍然被触发。

这不管用:

<div id="test">test</div>
<script>
$("#test").mouseup (function (e) {
  var a = 1;
  e.preventDefault();
});
$("#test").click (function (e) {
  var a = 2;
});
提问于
用户回答回答于

我也有同样的问题,也没有找到解决办法。但我想出了一个黑客似乎很管用。

由于onMouseUp处理程序似乎无法取消对一个链接的单击与预防性Default或停止事件或其他,我们需要使链接取消自己。这可以通过编写onClick属性来完成,该属性在拖动开始时向a-标记返回false,在拖动结束时将其移除。

而且,由于onDragEnd或onMouseUp处理程序是在浏览器解释单击之前运行的,所以我们需要检查拖动的结束位置和单击哪个链接等等。如果它结束于被拖动的链接之外(我们拖动了链接以便光标不再在链接上),我们将删除onDragEnd中的onClick处理程序;但是如果它结束于拖放链接上的游标(单击将被启动),则让onClick-处理程序自行删除。

不是完整的代码,但只是为了展示这个想法:

// event handler that runs when the drag is initiated
function onDragStart (args) {
  // get the dragged element
  // do some checking if it's a link etc
  // store it in global var or smth

  // write the onclick handler to link element
  linkElement.writeAttribute('onclick', 'removeClickHandler(this); return false;');
}

// run from the onclick handler in the a-tag when the onMouseUp occurs on the link
function removeClickHandler (element) {
  // remove click handler from self
  element.writeAttribute('onclick', null);
}

// event handler that runs when the drag ends
function onDragEnds (args) {
  // get the target element

  // check that it's not the a-tag which we're dragging,
  // since we want the onclick handler to take care of that case
  if (targetElement !== linkElement) {
    // remove the onclick handler
    linkElement.writeAttribute('onclick', null);
  }
}
用户回答回答于

使用事件捕获阶段

在要取消单击事件的元素周围放置一个元素,并向其添加捕获事件处理程序。

<div id="capture">
    <button id="test_capture">Test capture click event</button>
</div>
<script>
    $("#test_capture").mouseup(function (e) {
        alert('mouseup');
        var captureClick = function(e) {
            alert('click captured');
            e.stopPropagation(); // Stop the click from being propagated.
            this.removeEventListener('click', captureClick, true); // cleanup
        }
        $('#capture')[0].addEventListener(
            'click',
            captureClick,
            true // <-- This registeres this listener for the capture
                 //     phase instead of the bubbling phase!
        );
    });
    $("#test_capture").click(function (e) {
        alert('click');
    });
<script>

JSFiddle演示

发生了什么:

控件上的单击事件之前。button触发周围的单击事件。div因为它为捕获阶段而不是冒泡阶段注册了自己,所以会被触发。

captureClick处理程序然后停止它的传播click事件,并防止click要调用的按钮上的处理程序。这正是你想要的。然后,为了清理,它会自行移除。

捕获和冒泡:

捕获阶段从DOM根一直调用到Leafs,而冒泡阶段则是从叶到根

jQuery总是将事件添加到冒泡阶段,这就是为什么我们需要在这里使用纯JS来将捕获事件专门添加到捕获阶段。

记住,IE在IE9中引入了W3C的事件捕获模型,所以这不会适用于IE<9。

使用当前事件API,不能在已经添加的DOM元素之前向DOM元素添加新的事件处理程序。

扫码关注云+社区