JavaScript中DOM樹的事件流
阿新 • • 發佈:2018-11-19
圖片展示了DOM樹是如何使用事件流進行事件分發:
Dom樹中從最外層的Window至內層具體的html標籤都可以通過addEventListener(type, listener, useCapture)方法新增監聽事件。
捕獲階段(Capture Phase):
事件分發順序是從最外層的Window開始,按照順序:Window-Document-html-body-table-tbody-tr-td由外至內分發。
目標階段(Target Phase):
事件分發至真正被點選的元素。
冒泡階段(Bubbling Phase):
事件分發順序是從最內層的td開始,按照順序:td-tr-tbody-table-body-html-Document-Window由內往外分發,與事件捕獲順序相反。就像將一個石頭扔進水裡,氣泡由水底向水面上浮一樣。
例子:
<style> #testDiv, #testP, #testSpan{ margin: 5px; padding: 5px; box-sizing: border-box; cursor: default; } #testDiv{ width: 300px; height: 300px; border: indianred 3px solid; } #testP{ width: 200px; height: 200px; border: hotpink 3px solid; } #testSpan{ display: block; width: 100px; height: 100px; border: orange 3px solid; } </style>
<body>
<div id="testDiv">testDiv
<p id="testP">testP
<span id="testSpan">testSpan</span>
</p>
</div>
</body>
點選testSpan標籤佈局的橙色方框內部,控制檯的列印結果如下:<script> var testDiv = document.getElementById("testDiv"); var testP = document.getElementById("testP"); var testSpan = document.getElementById("testSpan"); // 捕獲,階段繫結事件 window.addEventListener("click", function(e){ console.log("window 捕獲,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); document.addEventListener("click", function(e){ console.log("document 捕獲,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); document.documentElement.addEventListener("click", function(e){ console.log("html 捕獲,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); document.body.addEventListener("click", function(e){ console.log("body 捕獲,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); testDiv.addEventListener("click", function(e){ console.log("testDiv 捕獲,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); testP.addEventListener("click", function(e){ console.log("testP 捕獲,,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); testSpan.addEventListener("click", function(e){ console.log("testSpan 捕獲,", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, true); // 冒泡階段繫結的事件 window.addEventListener("click", function(e){ console.log("window 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); document.addEventListener("click", function(e){ console.log("document 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); document.documentElement.addEventListener("click", function(e){ console.log("html 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); document.body.addEventListener("click", function(e){ console.log("body 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); testDiv.addEventListener("click", function(e){ console.log("testDiv 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); testP.addEventListener("click", function(e){ console.log("testP 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); testSpan.addEventListener("click", function(e){ console.log("testSpan 冒泡", "目標節點:" + e.target.nodeName, ", 當前節點:" + e.currentTarget.nodeName); }, false); </script>