如何在单击子锚点时阻止父级的onclick事件触发?

Jon*_*ney 315 javascript jquery event-propagation

我目前正在使用jQuery使div可点击,在这个div中我也有锚点.我遇到的问题是,当我点击一个锚点时,两个点击事件都会被触发(对于div和锚点).如何在单击锚点时阻止div的onclick事件触发?

这是破碎的代码:

JavaScript的

var url = $("#clickable a").attr("href");

$("#clickable").click(function() {
    window.location = url;
    return true;
})
Run Code Online (Sandbox Code Playgroud)

HTML

<div id="clickable">
    <!-- Other content. -->
    <a href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>
Run Code Online (Sandbox Code Playgroud)

Rex*_*x M 422

事件冒泡到DOM中连接了单击事件的最高点.因此,在您的示例中,即使您在div中没有​​任何其他明确可单击的元素,div的每个子元素也会将它们的click事件向上冒泡到DOM,直到DIV的click事件处理程序捕获它为止.

有两个解决方案是检查谁实际发起了事件.jQuery传递一个eventargs对象和事件:

$("#clickable").click(function(e) {
    var senderElement = e.target;
    // Check if sender is the <div> element e.g.
    // if($(e.target).is("div")) {
    window.location = url;
    return true;
});
Run Code Online (Sandbox Code Playgroud)

您还可以将单击事件处理程序附加到链接,告诉他们在执行自己的处理程序后停止事件冒泡:

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});
Run Code Online (Sandbox Code Playgroud)

  • 使用`if(e.target!== this)return;`中的`比子中的`e.stopPropagation()`更好,因为你永远不知道别人是否给孩子们添加了一些处理程序,或者库是否必须将处理程序附加到子代(并且您不想弄乱库代码).这是一个更好的关注点分离. (19认同)
  • 很好的答案.很高兴知道也有选择. (3认同)
  • +1!使用stopPropagation附加一个单击处理程序是一个非常好的技巧,谢谢! (3认同)
  • 如果你有一堆你希望阻止传播的元素,你可以找到它们的父元素和头部,防止它在那里冒泡.所以,不要拦截div中的所有链接,比如说 - 只是拦截点击甚至div本身,并防止它向上移动并且你已经设置好了. (2认同)
  • 将`if(e.target!== this)return;`放入父级检查意味着如果该父级的其他任何子级没有自己的onClick处理程序被单击,则不会发生任何事情。因此,对于您具有例如可点击的父div的情况,它是没有用的。`e.stopPropagation()`可以正常工作。 (2认同)
  • 值得注意的是,stopPropagation() 不会阻止在父级上检测到其他鼠标事件,因此带有 stopPropagation 的“click”事件不会停止使用“mouseup”附加到父级的事件。它很有道理而且很有用,但它让我有一段时间有点困惑 (2认同)

Cle*_*ton 93

使用stopPropagation方法,请参阅示例:

$("#clickable a").click(function(e) {
   e.stopPropagation();
});
Run Code Online (Sandbox Code Playgroud)

正如jQuery Docs所说:

stopPropagation 方法可防止事件冒泡DOM树,从而阻止任何父处理程序收到事件通知.

请记住,它不会阻止其他侦听器处理此事件(例如,按钮的多个单击处理程序),如果它不是所需的效果,则必须使用stopImmediatePropagation.


Sab*_*baz 44

这里我的解决方案适合所有人寻找非jQuery代码(纯javascript)

document.getElementById("clickable").addEventListener("click", function( e ){
    e = window.event || e; 
    if(this === e.target) {
        // put your code here
    }
});
Run Code Online (Sandbox Code Playgroud)

如果单击父项的子项,则不会执行您的代码

  • 很好的答案。我直接就通过了活动。所以我没有使用 MDN 不鼓励的 `window.event`:https://developer.mozilla.org/en-US/docs/Web/API/Window/event。如果您能抽出时间,如果您能评论一下为什么使用“window.event”(也许这是 2015 年存在的问题,或者我无法理解原因),我将不胜感激。 (5认同)

Ras*_*ara 14

你也可以试试这个

$("#clickable").click(function(event) {
   var senderElementName = event.target.tagName.toLowerCase();
   if(senderElementName === 'div')
   {
       // do something here 
   } 
   else
   {
      //do something with <a> tag
   }
});
Run Code Online (Sandbox Code Playgroud)


Hoo*_*ari 12

如果您不想在任何情况下与内部元素交互,那么CSS解决方案可能对您有用.

只需将内部元素设置为 pointer-events: none

在你的情况下:

.clickable > a {
    pointer-events: none;
}
Run Code Online (Sandbox Code Playgroud)

或者通常针对所有内部元素:

.clickable * {
    pointer-events: none;
}
Run Code Online (Sandbox Code Playgroud)

在使用ReactJS进行开发时,这个简单的黑客为我节省了大量时间

浏览器支持可以在这里找到:http://caniuse.com/#feat=pointer-events


Mat*_*eth 10

内联替代方案:

<div>
    <!-- Other content. -->
    <a onclick='event.stopPropagation();' href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>
Run Code Online (Sandbox Code Playgroud)


Sza*_*aci 10

我比较不可用的ev.currentTarget时间this(React 等)。

$("#clickable").click(function(e) {
    if (e.target === e.currentTarget) {
        window.location = url;
        return true;
    }
})
Run Code Online (Sandbox Code Playgroud)


Ima*_*eem 8

使用return false;e.stopPropogation();不允许执行更多代码.它会在此时停止流动.


Iva*_*vić 7

如果可点击的div中有多个元素,则应执行以下操作:

$('#clickable *').click(function(e){ e.stopPropagation(); });
Run Code Online (Sandbox Code Playgroud)


Bah*_*mir 5

如果有人需要写作(为我工作):

event.stopImmediatePropagation()
Run Code Online (Sandbox Code Playgroud)

这个解决方案.