私が理解しているように、DOM レベル 2 のイベント処理は次の順序で機能します。
- 先頭の HTML 要素からターゲットの前までずっとキャプチャする
- ターゲット自体
- 一番上の HTML 要素までバブリングする
例はhttps://jsfiddle.net/uwe5dmxw/
にあります
(この質問の最後にコードを含めます)
しかし、現在の Google Chrome、Firefox、Safari、さらには IE 11 で「子」要素 (最下位レベルの子孫) をクリックすると、次の順序で一貫した結果が得られます。
- HTML キャプチャ
- ボディキャプチャー
- 親のキャプチャ
- ターゲットバブリング
- ターゲットの捕獲
- 親バブリング
- BODYバブリング
- 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);