【问题标题】:Does stopPropgation stop the event from propagating in the capture phase?stopPropgation 是否会阻止事件在捕获阶段传播?
【发布时间】:2012-09-09 20:58:05
【问题描述】:

我在看http://www.quirksmode.org/js/events_order.html,这部分内容模棱两可:

在 Microsoft 模型中,您必须将事件的 cancelBubble 属性设置为 true

window.event.cancelBubble = true

在 W3C 模型中,您必须调用事件的 stopPropagation() 方法。

e.stopPropagation()

这会在冒泡阶段停止事件的所有传播。

所以我的问题是:

  • 当事件侦听器设置为在捕获阶段侦听时,它是否会自动不再继续传播到内部元素?
  • 或者如果它继续传播,是否调用e.stopPropagation() 会阻止它,还是只对冒泡阶段有效?

【问题讨论】:

    标签: javascript dom-events event-bubbling event-propagation


    【解决方案1】:

    简答:顺序是:

    1. 捕获(向下)
    2. 目标
    3. 气泡(向上)。

    如果你在捕获阶段调用e.stopPropagation()(通过将addEventListener()第三个参数设置为true),它会停在1,所以2 & 3 无法接收。

    如果您在冒泡阶段调用e.stopPropagation()(通过将addEventListener()第三个参数 设置为false 或不分配), 1 和 2 已经完成,所以它只是防止事件从您调用 stopPropagation() 的级别向上冒泡。

    【讨论】:

    • 我认为这个问题更具体。 event.stopPropagation() 是否阻止事件通过剩余的 event.target 的祖先下降?还是它只阻止第 2 阶段和第 3 阶段,而第 1 阶段无论如何都会完成?
    • 这是一个比目前被接受的更好的答案。
    【解决方案2】:

    不,事件侦听器不会阻止任何事件的传播,除非您明确告诉它这样做。您所指的部分专门处理泡沫阶段。 IE 的模型不支持事件捕获 - 句号。捕获阶段是冒泡阶段之前的阶段:

    Top of the DOM --->event--->traverses--->to--->[target]+[event]-| (capture phase)
          /\                                                       \/
          |------------------------to--------back up-----------------  (bubble up)
    

    【讨论】:

    • 谢谢。看起来 IE8 不支持事件捕获,但 IE9 支持:msdn.microsoft.com/en-us/library/windows/apps/hh453039.aspx
    • 我的问题是 e.stopPropagation() 只停止冒泡的传播,还是同时停止捕获和冒泡的传播?答案可能取决于浏览器。
    • 简短回答:stopPropagation 在这两种情况下都会停止事件。正如(可怕的)ASCII 图表所示,事件集从document 开始,并在 DOM 中下降,朝向触发事件的元素。之后,它会冒泡回到文档。在此过程之间的每一步都可以停止,无论是在捕获阶段还是冒泡阶段。
    • 好的,谢谢 :) 我认为我们实际上是在说同样的话...如果您在冒泡时停止,则捕获阶段已经完成,...因此,冒泡时停止不应阻止听众正在从处理事件中侦听捕获阶段。
    • 令人难以置信的是,这个答案 still 并没有真正回答这个问题(调用 e.stopPropagation() 会阻止它吗?),我们需要阅读厘米。 Answer by Leon li 好多了。
    【解决方案3】:

    stopPropagation() 不会阻止捕获的事件处理程序被调用。 stopPropagation() 将阻止冒泡事件处理程序被调用。

    Jsfiddle

    var outputDiv = document.getElementById('output');
    
    function log(msg) {
      outputDiv.insertAdjacentHTML('afterend', msg + '<br>');
    }
    
    /////////////////////
    //Bubbling listeners
    /////////////////////
    document.getElementById('row1').addEventListener('click', function(e) {
      log('Bubbling row1 listener called');
      e.stopPropagation();
    }, false);
    
    document.getElementById('row2').addEventListener('click', function(e) {
      log('Bubbling row2 listener called');
      //NO stopPropagation on this one.
    }, false);
    
    document.getElementById('table').addEventListener('click', function() {
      log('Bubbling table listener called');
    }, false);
    
    
    document.addEventListener('click', function() {
      log('Bubbling document listener called');
    }, false);
    
    /////////////////////
    //Capturing listeners
    /////////////////////
    document.addEventListener('click', function() {
      log('Capturing document listener called');
    }, true);
    
    document.getElementById('table').addEventListener('click', function() {
      log('Capturing table listener called');
    }, true);
    #outputwrapper {
      border: 1px solid black;
      height: 300px;
      overflow: scroll;
    }
    <table id="table" border="1">
      <tbody>
        <tr>
          <td id="row1">
            This row has stopPropagation
          </td>
        </tr>
        <tr>
          <td id="row2">
            This row does not have stopPropagation
          </td>
        </tr>
      </tbody>
    </table>
    <br>Output
    <br>
    <div id="outputwrapper">
      <div id="output"></div>
    </div>

    【讨论】:

    • 你有两个问题。首先,它们是第 1 行和第 2 行,而不是列。其次,第 2 行的事件处理程序实际上不在捕获阶段,因为它的addEventListener 的第三个参数丢失了。接受的答案是正确的。
    • @Chen 首先我同意专栏的用词不当。实际上,我已经通过删除一些列来缩短代码,并保留了这些代码。
    • @Chen 我已经修改了代码以反映我试图解释的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多