无法理解 addEventListener 中的 useCapture 参数

2022-08-29 23:49:34

我读过 https://developer.mozilla.org/en/DOM/element.addEventListener 的文章,但无法理解属性。定义有:useCapture

如果为 true,则 useCapture 指示用户希望启动捕获。启动捕获后,指定类型的所有事件都将分派给已注册的侦听器,然后再分派到 DOM 树中其下的任何事件目标。通过树向上冒泡的事件不会触发指定使用 capture 的侦听器。

在此代码中父事件在子事件之前触发,因此我无法理解其行为。文档对象具有 usecapture true,子 div 具有 usecapture set false,并且文档 usecapture 被遵循。那么为什么文档属性优先于子属性。

function load() {
  document.addEventListener("click", function() {
    alert("parent event");
  }, true);

  document.getElementById("div1").addEventListener("click", function() {
    alert("child event");
  }, false);
}
<body onload="load()">
  <div id="div1">click me</div>
</body>

答案 1

事件可以在两种情况下激活:在开始(“捕获”)和结束时(“气泡”)。事件按其定义顺序执行。假设您定义了 4 个事件侦听器:

window.addEventListener("click", function(){console.log(1)}, false);
window.addEventListener("click", function(){console.log(2)}, true);
window.addEventListener("click", function(){console.log(3)}, false);
window.addEventListener("click", function(){console.log(4)}, true);

日志消息将按以下顺序显示:

  • 2(首先定义,使用capture=true)
  • 4(定义第二次使用capture=true)
  • 1(第一个定义的事件capture=false)
  • 3(第二个定义的事件capture=false)

答案 2

我发现这个图表对于理解捕获/目标/气泡阶段非常有用:http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

下面是从链接中提取的内容。

阶段

该事件按照从树根目录到此目标节点的路径进行调度。然后,可以在目标节点级别本地处理它,也可以从树中更高位置的任何目标的祖先处理它。事件调度(也称为事件传播)分三个阶段和以下顺序进行:

  1. 捕获阶段:将事件从树的根发送到目标节点的直接父节点,发送到目标的祖先。
  2. 目标阶段:将事件调度到目标节点。
  3. 冒泡阶段:事件从目标节点的直接父节点到树的根,调度到目标的祖先。

graphical representation of an event dispatched in a DOM tree using the DOM event flow

目标的祖先是在事件的初始调度之前确定的。如果在调度期间移除了目标节点,或者添加或删除了目标的祖先,则事件传播将始终基于目标节点和在调度之前确定的目标的祖先。

某些事件可能不一定完成 DOM 事件流的三个阶段,例如,事件只能为一个或两个阶段定义。例如,本规范中定义的事件将始终完成捕获阶段和目标阶段,但有些事件不会完成冒泡阶段(“冒泡事件”与“非冒泡事件”,另请参阅 Event.bubbles 属性)。