父级点击事件与子级点击事件重叠

4
我希望您能够点击父级div,但子级表单和锚元素不受点击事件影响。
<div class="root">

    <div class="parent">
        <div class="container">
            <a href="/blah"> Hello World</a>
            <div>
                <span> Hello World Again
            </div>
            <form class="form">
                <label> inputs
                <input id="text" type="text"/>
                <textarea></textarea>
                <input id="submit" type="submit"/>
            </form>
        </div>
    </div>

</div>

jQuery:

$(".parent").on("click", ".container", function() {
    alert("Parent clicked");
});

$(".parent").on("click", "#text", function(event) {
    event.preventDefault();
    alert("Form Input clicked");
});

$(".parent").on("click", "#submit", function(event) {
    event.preventDefault();
    alert("Form Button clicked");
});

 $(".parent").on("click", "a", function(event) {
    event.preventDefault();
    alert("anchor link clicked");
});   

点击表单元素(input、textarea、button submit)或锚标签都不起作用,因为父级点击事件正在触发。
如何使父级点击事件仅在子表单和锚标签之外的元素上生效?父级点击事件可以覆盖除这两个元素之外的任何其他子元素。
1个回答

5

你有两个选择:

  1. Hook the click event on the relevant child container (it looks like it would be the form) and use event.stopPropagation() within the handler. That will stop the event bubbling to the parent. Something like this:

    // Option 1: Hook on the form and stop
    // propagation (hooking up "false" does an
    // implicit preventDefault + stopPropagation)
    $(".parent").on("click", "form", false);
    
  2. Inside the parent's handler, check to see if the parent element is the element that was the source of the event (e.target). If it is, process the event; if it isn't, ignore it, it was generated on a child element. Something like this:

    $(".parent").on("click", ".container", function(event) {
        // Option 2: Look at event.target and ignore
        // the event if it originated in a descendant
        // element
        if (this === event.target) {
            alert("Parent clicked");
        }
    });
    
请注意,这两个功能略有不同。第一个功能说“防止父级看到表单上的点击”,而第二个功能则说“忽略不直接作用于 .parent .container 的点击”。当然,也可以通过不同的目标进行适应。
实时示例:

抱歉,我忘记了闭合锚点标签。我已经编辑了我的帖子并加入了它。 - user21398
@user21398:啊!这就解释了。我应该仔细看一下的。 - T.J. Crowder
第二种方法似乎不适合我的情况,主要是因为我希望其他子元素也能被父级的点击所覆盖。因此,“Hello World Again” div/span 应该受到父级点击的影响,而锚点和表单则不应该。第一种方法有效,但它似乎会防止表单内的任何其他元素被点击,例如提交按钮无法触发自己的点击处理程序,这是一个大问题。 - user21398
@user21398:在我上面的示例中,它没有问题,单击提交按钮可以正常工作。这很棘手,因为所有处理程序都是委派的,但我检查了一下它们连接的顺序是否有问题,似乎并不重要 - T.J. Crowder
@user21398:正如我上面所提到的,第二个选项可以适应各种情况。例如,假设您只想忽略特定元素上的点击:if ($(event.target).closest("#text, #submit, .container").hasClass("container")) {示例)。这将允许在.container内部单击其他元素,前提是它们不是#text#submit - T.J. Crowder
1
刚刚也尝试了第二种方法,似乎是一种更灵活的方式。好知道! - user21398

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