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


346

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

这是损坏的代码:

的JavaScript

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

$("#clickable").click(function() {
    window.location = url;
    return true;
})

的HTML

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

Answers:


458

事件冒泡至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;
});

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

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});

3
好答案。很高兴知道也有其他选择。
Jonathon Watney

4
+1!附加带有stopPropagation的单击处理程序是一个非常好的技巧,谢谢!
Thomas

2
如果您有一堆要防止传播的元素,则可以找到它们的父元素并阻止它在那里冒泡。因此,例如,与其拦截div中的所有a链接,不如拦截div本身上的点击,并防止其进一步升高,您就可以设置了。
最终

21
if( e.target !== this) return;在父级中使用比e.stopPropagation()在子级中使用更好,因为您不知道其他人是否将某些处理程序附加到子级上,或者库是否必须将处理程序附加到子级上(并且您不希望弄乱库代码)。这是更好的关注点分离。
UTF_or_Death

3
if( e.target !== this) return;支票放在父项中意味着如果该父项的其他任何子项都没有自己的onClick处理程序,则单击该子项,则不会发生任何事情。因此,对于您具有例如可点击的父div的情况,它是没有用的。e.stopPropagation()工作正常。
derf26 '18

100

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

$("#clickable a").click(function(e) {
   e.stopPropagation();
});

正如jQuery Docs所说:

stopPropagation 方法防止事件使DOM树冒泡,从而防止任何父处理程序收到该事件的通知。

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


48

在这里,我为所有人寻找非jQuery代码的解决方案(纯JavaScript)

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

如果单击父母的孩子,您的代码将不会执行


1
这对我有用,我需要一个非JS / jQuery解决方案。10倍!
2016年

好答案。我刚刚直接通过了活动。因此,我没有使用window.eventMDN不鼓励使用的内容:developer.mozilla.org/en-US/docs/Web/API/Window/event。如果您能抽出宝贵的时间,如果您可以评论使用原因window.event(可能是2015年存在的问题,或者我无法理解原因),我们将不胜感激。
RMo

15

你也可以试试这个

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

14

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

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

在您的情况下:

.clickable > a {
    pointer-events: none;
}

或针对所有内部元素:

.clickable * {
    pointer-events: none;
}

在使用ReactJS开发时,这种简单的技巧为我节省了很多时间

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



8

使用return false;e.stopPropogation();将不允许执行其他代码。此时它本身将停止流动。


是的,这很重要-自己遇到了。但是上面来自Rex的答案很有帮助-可以获取被单击的元素,并且在某些情况下,请在尝试停止的逻辑中使用此元素。.target.nodeName还可帮助您清楚了解被击中的内容。
Watercayman's


4

内联替代:

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

3

这是使用Angular 2+的示例

例如,如果您想在用户单击外部时关闭模态组件,请执行以下操作:

// Close the modal if the document is clicked.

@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
  this.closeModal();
}

// Don't close the modal if the modal itself is clicked.

@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
  event.stopPropagation();
}


1

var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);

function innerFunction(event){
  event.stopPropagation();
  console.log("Inner Functiuon");
}

function outerFunction(event){
  console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
  <div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>


0

要将某些子元素指定为不可点击,请编写css层次结构,如下例所示。

在此示例中,我停止传播到类为“ .subtable”的表中tr内部td内的任何元素(*)

$(document).ready(function()
{    
   $(".subtable tr td *").click(function (event)
   {
       event.stopPropagation();
   });

});

0

ignoreParent()是纯JavaScript解决方案。

它用作将鼠标单击的坐标与子元素的坐标进行比较的中间层。两个简单的实现步骤:

1.在页面上放置ignoreParent()代码。

2。代替父母原来的onclick =“ parentEvent();” ,写:

onclick="ignoreParent(['parentEvent()', 'child-ID']);"

您可以将任意数量的子元素的ID传递给该函数,并排除其他子元素。

如果单击子元素之一,则不会触发父事件。如果单击父级,但未单击任何子级元素(作为参数提供),则会触发父级事件。

Github上的ignoreParent()代码


-1

万一有人使用React遇到了这个问题,这就是我解决的方法。

scss:

#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }

#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }

组件的render():

render() {
    ...
    return (
        <div id='loginBackdrop' onClick={this.props.closeLogin}>
            <div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
             ... [modal content] ...
            </div>
        </div>
    )
}

通过为子模式(内容div)添加onClick函数,可以防止鼠标单击事件到达父元素的“ closeLogin”函数。

这帮了我大忙,我就能用2个简单的div创建一个模态效果。


-3

添加a如下:

<a href="http://foo.com" onclick="return false;">....</a>

return false;从点击处理程序中获取,#clickable例如:

  $("#clickable").click(function() {
        var url = $("#clickable a").attr("href");
        window.location = url;
        return false;
   });

-3

所有解决方案都很复杂,而且是jscript。这是最简单的版本:

var IsChildWindow=false;

function ParentClick()
{
    if(IsChildWindow==true)
    {
        IsChildWindow==false;
        return;
    }
    //do ur work here   
}


function ChildClick()
{
    IsChildWindow=true;
    //Do ur work here    
}

3
我认为您在“ IsChildWindow == false;”行中犯了一个错误。-不是“ IsChildWindow = false;”吗?
Andre Schweighofer 2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.