DOM的Event flow概念,指的是「網頁元素接收事件的順序」。
假如有兩個重疊的<div>,外層是outer內層是inner:
由於inner被包在outer裡面,所以當我們點擊inner時,也代表我們也點擊到了outer;若再將範圍擴大,實際上我們也點擊了整個網頁。
而上面這樣子的事件傳播概念即是Event Flow - 事件流,Event Flow可分為以下兩種方式:
當 DOM 事件發生時,事件會先由外到內 (capturing phase)、再由內到外 (bubbling phase) 的順序來傳播。
根據 W3C 所定義的 Event Flow:
如下範例:
<html>
<head>
<title>Event flow</title>
</head>
<body>
<div>
<ul>
<li></li>
</ul>
</div>
</body>
</html>
document
-> <html>
-> <body>
-> <div>
-> <ul>
-> <li>
<li>
-> <ul>
-> <div>
-> <body>
-> <html>
-> document
另外,在 addEventListener 和 removeEventListener 方法中,可以傳遞第三個參數(布林值),用來指定事件處理函數是要在 Capturing 階段或 Bubbling 階段被執行。
如果是false就用事件冒泡(bubbling),如果是true就使用事件捕捉(capturing)。
沒寫的話,預設就是false,也就是預設使用事件冒泡(bubbling)機制:
element.addEventListener('click', eventHandler) // 未指定,預設為冒泡
element.addEventListener('click', eventHandler, false) // 冒泡
element.addEventListener('click', eventHandler, true) // 捕獲
範例
<div id="parent">
父元素
<div id="child">子元素</div>
</div>
var parent = document.getElementById("parent");
var child = document.getElementById("child");
parent.addEventListener("click", function() {
console.log("Parent capturing")
}, true);
parent.addEventListener("click", function() {
console.log("Parent bubbling")
}, false);
child.addEventListener("click", function() {
console.log("Child capturing")
}, true);
child.addEventListener("click", function() {
console.log("Child bubbling")
}, false);
當點擊父元素時,console.log的結果為:
Parent capturing
Parent bubbling
當點擊子元素時,console.log的結果為:
Parent capturing
Child capturing
Child bubbling
Parent bubbling
以上結果可見,當點擊子元素時,會先從外層的父元素開始傳遞,再到內層子元素,再從子層回到父層。
參考資料:
https://www.fooish.com/javascript/dom/event.html
https://ithelp.ithome.com.tw/articles/10191970