子项和父项都是可单击的(子项可以是具有jQuery click事件的链接或div)。单击子级时,如何仅触发父级单击事件而不触发子级事件?

最佳答案

DOM事件阶段
Activity 分为三个阶段:

  • 捕获:第一阶段是“捕获”,其中从<window>开始调用事件处理程序,然后向下通过后代向事件目标移动。
  • 目标:第二阶段是调用目标上的事件侦听器时的“目标”阶段。
  • 冒泡:第三阶段是“冒泡”,它始于处理程序先侦听目标的父对象,然后逐步侦听该元素的祖先。
    事件也有一个“默认 Action ”,发生在冒泡阶段之后。默认操作是浏览器定义的操作,通常会在作为事件目标的元素类型上针对指定类型的事件发生(例如,浏览器在href上导航至<a>click,而在另一目标上导航至click)元素类型将具有不同的默认操作)。
    DOM Level 3 Events draft的图表以图形方式显示事件如何通过DOM传播:
    javascript - 当 child 被点击时,如何仅触发 parent 点击事件-LMLPHP
    图片版权©2016 World Wide Web Consortium,(MITERCIMKeioBeihang)。 http://www.w3.org/Consortium/Legal/2015/doc-license(每个the license允许使用)
    有关捕获和冒泡的更多信息,请参见:“What is event bubbling and capturing?”; DOM Level 3 Events draft;或W3C DOM4: Events
    防止事件传给 child
    对于您想要的,要在父项上获得事件并在子项上阻止事件之前,您必须在捕获阶段接收事件。在捕获阶段接收到该事件后,您必须停止将该事件传播到DOM树中较低元素上的任何事件处理程序,或者已注册要在冒泡阶段中进行侦听的事件处理程序(即,将在元素/阶段中侦听的所有侦听器)在您的听众之后被该事件访问)。您可以通过调用 event.stopPropagation() 来实现。
    在捕获阶段接收事件
    在使用 addEventListener(type, listener[, useCapture]) 添加侦听器时,可以将useCapture参数设为true
    报价MDN:

    防止其他处理程序获取事件
  • event.preventDefault() 用于阻止默认操作(例如,防止浏览器在href上导航到<a>click)。 [在下面的示例中使用了此方法,但是由于没有针对文本的默认操作,因此没有实际效果。之所以在这里使用它,是因为在大多数情况下,当您添加单击事件处理程序时,您都想阻止默认操作。因此,养成这样做的习惯是一个好主意,并且当您知道自己不想这么做时就不要这样做。]
  • event.stopPropagation() 用于防止稍后在任何事件阶段中的元素上的任何处理程序接收事件。它不会阻止调用当前元素和阶段上的任何其他处理程序。它不会阻止默认操作的发生。
  • event.stopImmediatePropagation() :相同元素和阶段上的处理程序将按添加顺序被调用。除了具有与event.stopPropagation()相同的效果外,event.stopImmediatePropagation()还可以防止同一元素和事件阶段上的任何其他处理程序接收事件。它不会阻止默认操作的发生。鉴于此问题的要求是防止事件传播给 child ,因此我们不需要使用此方法,但可以这样做,而不是使用event.stopPropagation()。但是请注意,按添加元素的顺序调用同一元素上的侦听器。因此,event.stopImmediatePropagation()不会阻止与您的侦听器相同的元素和阶段中的那些侦听器接收到该事件,这些元素和相位是在您的侦听器之前添加的。


  • 在以下示例中,事件侦听器放置在父<div>元素和子event.stopPropagation()元素上。只有放置在父级上的侦听器会接收到该事件,因为它在子级之前的捕获阶段中接收到该事件,并执行ojit_code。

    var parent=document.getElementById('parent');
    var child=document.getElementById('child');
    var preventChild=document.getElementById('preventChild');
    
    parent.addEventListener('click',function(event){
        if(preventChild.checked) {
            event.stopPropagation();
        }
        event.preventDefault();
        var targetText;
        if(event.target === parent) {
            targetText='parent';
        }
        if(event.target === child) {
            targetText='child';
        }
        console.log('Click Detected in parent on ' + targetText);
    },true);
    
    child.addEventListener('click',function(event){
        console.log('Click Detected in child (bubbling phase)');
    });
    
    child.addEventListener('click',function(event){
        console.log('Click Detected in child (capture phase)');
    },true);
    <input id="preventChild" type="checkbox" checked>Prevent child from getting event</input>
    <div id="parent">Parent Text<br/>
      <div id="child" style="margin-left:10px;">Child Text<br/>
      </div>
    </div>

    jQuery的
    jQuery不支持在事件上使用捕获。有关原因的更多信息,请参见:“Why does jQuery event model does not support event Capture and just supports event bubbling

    07-24 09:50
    查看更多