为什么捕获阶段不会被event.stopPropagation打断?

时间:2019-01-22 16:27:06

标签: javascript event-handling dom-events stoppropagation event-propagation

如果运行此代码并单击P,将执行整个捕获阶段,但是冒泡阶段将按预期在div上停止。此代码有什么问题?

  for(let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => alert(`Capturing: ${elem.tagName}`), true);
    elem.addEventListener("click", e => alert(`Bubbling: ${elem.tagName}`));
  }
<form>FORM
  <div onclick="event.stopPropagation()">DIV
    <p>P</p>
  </div>
</form>

1 个答案:

答案 0 :(得分:1)

捕获阶段不会中断,因为在现代浏览器中,事件默认情况下是在冒泡阶段注册的(因此,onclick()元素中的<div>事件不会与您注册的单独事件处理程序交互在捕获阶段)。

我不知道一种通过html属性注册捕获阶段事件处理程序的方法(在某些较早的浏览器中,默认情况下在捕获阶段注册了事件)。

有关我认为可能是您最初打算的代码的修改版本,请参见下面的代码段。您将看到该代码在捕获阶段和冒泡阶段处理程序中调用stopPropagation()(在两种情况下均会产生预期的结果)。

for (let elem of document.querySelectorAll('*')) {
  
  elem.addEventListener('click', (e) => {
    if (elem.tagName === 'DIV') {
      e.stopPropagation();
    }
    console.log(`Capturing: ${elem.tagName}`);
  }, true);
  
  elem.addEventListener('click', (e) => {
    if (elem.tagName === 'DIV') {
      e.stopPropagation();
    }
    console.log(`Bubbling: ${elem.tagName}`);
  });

}
<form>
  form
  <div>
    div (click here)
    <p>p</p>
  </div>
</form>

在捕获阶段,浏览器从最外面的父级开始处理处理程序,因此直到它已经为所有父级元素{{1}处理过stopPropagation()处理程序之后,它才遇到click。 },<html>

在冒泡阶段,它将处理事件处理程序,该事件处理程序从被单击的元素向外移动到父元素开始。