2

私が理解しているように、DOM レベル 2 のイベント処理は次の順序で機能します。

  1. 先頭の HTML 要素からターゲットの前までずっとキャプチャする
  2. ターゲット自体
  3. 一番上の HTML 要素までバブリングする

例はhttps://jsfiddle.net/uwe5dmxw/
にあります (この質問の最後にコードを含めます)

しかし、現在の Google Chrome、Firefox、Safari、さらには IE 11 で「子」要素 (最下位レベルの子孫) をクリックすると、次の順序で一貫した結果が得られます。

  1. HTML キャプチャ
  2. ボディキャプチャー
  3. 親のキャプチャ
  4. ターゲットバブリング
  5. ターゲットの捕獲
  6. 親バブリング
  7. BODYバブリング
  8. HTML バブリング

すなわち、「ターゲット捕捉」と「ターゲットバブリング」の順序が逆になる。

私が理解しているように、DOM レベル 2 のイベントはターゲットに 1 回しか到達しないと言われていますが、ほとんどのブラウザは、イベントのキャプチャ中に 1 回、イベントのバブリング中に 1 回、2 回到達するように実装しています。しかし、実際には、なぜ「ターゲットのキャプチャ」と「ターゲットのバブリング」が逆になっているのでしょうか。


コード: (ただのデモです。必要がなければ見る必要はありません)

<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。両方のイベント ハンドラーに送信される同じイベント (クリック イベント) が表示されますが、イベント ハンドラーがアタッチされた順序で送信されます。

イベント ハンドラーが割り当てられている順序を逆にすると、イベント ハンドラーが呼び出される順序も変わることがわかります。イベントは「ターゲット」であり、バブリングまたはキャプチャーではないため、両方が呼び出されます。

2 つのターゲット イベント ハンドラーのそれぞれについてログを記録すると、"ターゲットにある" (バブリングまたはキャプチャーではない) ことを意味するe.eventPhase値がログに記録されていることがわかります。2の詳細については、MDN のドキュメントを参照してくださいe.eventPhase

于 2016-01-23T06:31:22.943 に答える