jQuery停止子元素触发父元素事件。

240

我有一个div,我已经将onclick事件附加到该div上。在此div中有一个带有链接的标签。当我点击链接时,也会触发div的onclick事件。如何禁用此功能,以便在div上单击链接时不会触发onclick事件?

脚本:

$(document).ready(function(){
    $(".header").bind("click", function(){
         $(this).children(".children").toggle();
    });
})

HTML 代码:

<div class="header">
    <a href="link.html">some link</a>
    <ul class="children">
        <li>some list</li>
    </ul>
</div>
7个回答

447

2
如果有帮助的话,我把 $(".header a") 替换成了 $(".header *") 并且选中了任何子元素(如 div、form、input 等)。 - aldo.roman.nurena
2
e.stopPropagation(); 必须写在第一行,除非它不起作用! - ehsan
2
遗憾的是,这种方法阻止了“rel”配置的灯箱功能。 - eapo
9
xr280xr 下面的回答更好,因为它不会干涉到孩子们可能发生的事件。 - Alexander Jank
2
你制造的问题比你解决的问题还多。想象一下第三方插件监听文档元素上的点击事件。他们永远不会知道这些点击事件。请参见有关灯箱的注释。 - Salman A
显示剩余2条评论

126

或者,与其添加额外的事件处理程序来防止另一个处理程序,您可以使用传递给单击事件处理程序的Event Object参数来确定是否单击了子元素。 target将是被单击的元素,currentTarget将是.header div:

$(".header").click(function(e){
     //Do nothing if .header was not directly clicked
     if(e.target !== e.currentTarget) return;

     $(this).children(".children").toggle();
});

9
对我而言,这是一种更优雅的解决方案,因为你不需要在每个子元素中添加显式的preventDefault()。 - Ryan Griggs
6
如果孩子之间的事件是独立的,那么这个方法是可行的,这比接受的答案更加简洁、更好。 - BozanicJosip
2
在大多数情况下,您可能不关心这一点,但如果出于某种原因您需要支持IE6-8,则它们没有currentTarget。解决方法是用this替换它,如另一个答案中建议的那样。 - Alexander Jank
太棒了!救命稻草 :-) - Grashopper
这对我非常有效。在我的情况下,我有一个在移动设备上高度为100%的菜单。在ul视图中查看。我想要在某人点击ul时折叠我的菜单,但同时也会在点击li时触发折叠。这个解决方法可以防止这种情况发生。 - Loopy
显示剩余4条评论

24
使用链接 on() 以链式方式改进,例如,
$(document).ready(function(){
    $(".header").on('click',function(){
        $(this).children(".children").toggle();
    }).on('click','a',function(e) {
        e.stopPropagation();
   });
});

@xr280xr - 抱歉,我把它和 .net 搞混了,那里从事件处理程序返回 false 是终止传播的一种方式。我已删除我的错误评论。 - ToolmakerSteve

7
我徘徊在这个问题上,寻找另一个答案。
我想要防止所有子元素触发父元素。
JavaScript:
document.getElementById("parent").addEventListener("click", function (e) {
    if (this !== event.target) return;
    // Do something
});

jQuery:

$("#parent").click(function () {
    // Do something
}).children().on("click", function (e) {
    e.stopPropagation();
});

第一部分类似于[xr280xr]早先的回答,但是使用纯JavaScript。第二个代码片段与被接受的答案相同的限制/缺陷(请参阅评论)-而应该使用在第一个代码片段中显示的技术-请参阅xr280xr的答案,以了解jquery的更好技术。 - ToolmakerSteve

4
这里的回答太过字面化了。如何将这些答案扩展到有许多子元素的情况下,而不仅仅是单个 <a> 标签?以下是一种方法。
假设您有一个带有黑色背景和浏览器中心对齐的照片库。当您单击黑色背景(但不包括其中任何内容)时,您希望覆盖层关闭。
以下是一些可能的 HTML:
<div class="gallery" style="background: black">
    <div class="contents"> <!-- Let's say this div is 50% wide and centered -->
        <h1>Awesome Photos</h1>
        <img src="img1.jpg"><br>
        <img src="img2.jpg"><br>
        <img src="img3.jpg"><br>
        <img src="img4.jpg"><br>
        <img src="img5.jpg">
    </div>
</div>

以下是JavaScript的工作方式:

$('.gallery').click(
    function()
    {
        $(this).hide();
    }
);

$('.gallery > .contents').click(
    function(e) {
        e.stopPropagation();
    }
);

这将阻止位于.contents内的元素的点击事件在每次查找.gallery时触发,因此只有当您单击淡化的黑色背景区域时,画廊才会关闭,而不是当您单击内容区域时。这可以应用于许多不同的情况。

3
最简单的解决方案是将此CSS添加到子元素中:
.your-child {
    pointer-events: none;
}

我需要这个来解决 WordPress 添加的不必要的字体标签问题,它对我很有效。 - TechNerdXp
这是我找到的最简单的方法。 - temo

0

或者这样:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        return false;
   });
});

2
@Halcyon991 无论如何,e 都会通过参数传递进来,e 只是一个引用。 - qodeninja
@qodeninja 是的,但如果不使用它,这是一个不必要的字符添加。 - Stephen Jenkins
不要在链接中添加 return false,它应该是可点击的。 - eapo

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