2

据我了解,DOM Level 2 事件处理按以下顺序工作:

  1. 从顶部 HTML 元素一直捕获到目标之前
  2. 目标本身
  3. 一直冒泡回到顶部的 HTML 元素

示例位于:https
://jsfiddle.net/uwe5dmxw/ (我将在此问题末尾包含代码)

但是,如果我在当前的 Google Chrome、Firefox、Safari 甚至 IE 11 上单击“子”元素(最低级别的后代),我会按以下顺序得到一致的结果:

  1. HTML 捕获
  2. 身体捕捉
  3. 父捕获
  4. 目标冒泡
  5. 目标捕获
  6. 父冒泡
  7. 身体冒泡
  8. HTML 冒泡

即,“目标捕获”和“目标冒泡”的顺序颠倒了。

据我了解,虽然 DOM Level 2 表示事件仅到达目标一次,但大多数浏览器将其实现为两次到达,一次是在事件捕获期间,一次是在事件冒泡期间。但事实是,为什么“目标捕获”和“目标冒泡”是相反的?


代码:(不过只是个demo,没必要不用看)

<div id="hi">
  hello
  <div id="child">
    child
  </div>
</div>

JavaScript:

var parentElement = document.getElementById("hi"),
  childElement = document.getElementById("child"),
  htmlElement = document.getElementsByTagName("html")[0],
  bodyElement = document.getElementsByTagName("body")[0];

// ------------------ Bubble --------------------

htmlElement.addEventListener("click", function() {
  console.log("<html> clicked " + new Date().getTime(), this);
});

bodyElement.addEventListener("click", function() {
  console.log("<body> clicked " + new Date().getTime(), this);
});

parentElement.addEventListener("click", function() {
  console.log("Parent clicked " + new Date().getTime(), this);
});

childElement.addEventListener("click", function() {
  console.log("Child clicked at " + new Date().getTime(), this);
});

// ------------------ Use Capture --------------------

htmlElement.addEventListener("click", function() {
  console.log("<html> (useCapture) clicked " + new Date().getTime(), this);
}, true);

bodyElement.addEventListener("click", function() {
  console.log("<body> (useCapture) clicked " + new Date().getTime(), this);
}, true);

parentElement.addEventListener("click", function() {
  console.log("Parent (useCapture) clicked " + new Date().getTime(), this);
}, true);

childElement.addEventListener("click", function() {
  console.log("Child (useCapture) clicked at " + new Date().getTime(), this);
}, true);
4

1 回答 1

3

当具有多个事件处理程序的对象上发生事件时,事件处理程序将按照它们附加的顺序被触发。您没有在 上看到单独的事件child。您会看到发送到两个事件处理程序的相同事件(单击事件),但按照附加事件处理程序的顺序发送。

如果您颠倒分配事件处理程序的顺序,您将看到事件处理程序也改变了它们被调用的顺序。该事件是“在目标”,而不是冒泡或捕获,因此两者都被调用。

如果您记录e.eventPhase两个目标事件处理程序中的每一个,您将看到它记录的值2意味着它“在目标”(不是冒泡或捕获)。有关更多信息,请参阅MDN 上的文档e.eventPhase

于 2016-01-23T06:31:22.943 回答