如何在点击子元素时忽略点击事件

27

所以我有以下场景:

<div id="block">
Sample text.
<a href="#">Anchor link</a>
</div>

<script type="text/javascript">
    $("#block").click(function() { alert('test'); });
</script>

我在div内的任何位置单击时,都会弹出“test”提示。但是,当我单击“锚链接”时,我想阻止这种情况发生。如何实现这一点?

谢谢

5个回答

31

您可以通过添加额外的处理程序来阻止来自链接的点击事件向上传递,像这样:

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

我们在评论中讨论的替代方案:

$("#block").delegate('a', 'click', function(e){ e.stopImmediatePropagation(); })
           .click(function() { alert('test'); });​

这将阻止任何子链接冒泡(实际上并不是这样,但它们的处理程序不会执行),但不会为每个元素创建一个处理程序,这是通过.stopImmediatePropagation()完成的。


4
为了防止事件冒泡,对于每个链接都添加一个点击处理程序,可能会有点过度(当然这取决于链接的数量)。但这是一种防止特定元素事件冒泡的好方法。 - Felix Kling
@Felix - 如果有很多链接,我会完全采用一组.delegate()处理程序的不同方法 :) (您还可以在其他单击处理程序之前使用上面的委托版本)。 - Nick Craver
我刚刚尝试了delegate(),但对我无效:http://jsfiddle.net/cxcfA/。我猜是因为事件已经冒泡了。或者你是指其他什么? - Felix Kling
@Felix - e.stopImmediatePropagation(); ;) http://jsfiddle.net/nick_craver/cxcfA/1/ - Nick Craver
非常好 :) 很棒!你似乎总是有答案 ;) - Felix Kling
jQuery 中有一个 bug,delegate 函数不返回对象。 - Elie

16

9
您可以使用事件对象的 target 属性来测试哪个节点被点击了:
$("#block").click(function(event) { 
    if(event.target.nodeName != 'A') {
        alert('test');
    }
});

我建议阅读来自quirksmode.org的事件属性

4
$("#block").click(function(event) {
    if($(event.target).attr('id') == $(this).attr('id'))
    {
        alert('test');
    }
});

非常好用。谢谢! - hiroki

0

这里有一个演示(jsfiddle),包含一个表单和两个字段:

<div id="container">
    <form>
        <div class="field">
            <input id="demo" type="text" name="demo" />
        </div>
        <div class="field">
            <input id="demo2" type="text" name="demo2" />
        </div>
    </form>
</div>

代码看起来像这样:
$(document).ready(function() {
    $('#container').click(function(evt) {
        if(this == evt.target) {
            console.log('clicked container',evt.target);
            $('#demo').focus();
        } else {
            console.log('clicked child -> ignoring');
        }
    });

    $('.field').click(function(evt) {
        if(this == evt.target) {
            console.log('clicked field div',evt.target);
            $(this).find('input').focus();
        } else {
            console.log('clicked child -> ignoring');
        }
    });
});

您可以点击包含表单的容器,将焦点设置在第一个输入字段上或在输入字段后面将焦点设置到其中。
如果您点击输入字段,则会忽略该操作。
上述代码有效,因为jQuery在调用事件处理程序之前将DOM节点分配给this,因此您可以轻松地检查当前事件是否由DOM节点发布,方法是检查。
this == evt.target

CSS:

#container {
    width: 600px;
    height: 600px;
    background: blue;
}

.field {
    background: green;
}

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