目標
EventTarget.addEventListener
中事件的 capture
、bubble
與 once
方法,以及事件代理(propagation)
step 1 : 了解 HTML 的架構與建立 click 監聽事件
<div class="one">
<div class="two">
<div class="three">
</div>
</div>
</div>
// 取得頁面的所有 div 元素
const divs = document.querySelectorAll('div');
function logText(e){
// console 印出當前 click 的 class name
console.log(this.classList.value);
}
// 監聽所有 div 元素的 click 事件
divs.forEach(div => div.addEventListener('click',logText));
step 2 : 點擊最裡面的 class name 為 three 的區塊,並查看 console.log 的結果
發現印出從最内層到最外層(three -> two -> one)
three
two
one
step 3 : 分析 addEventListener 的參數
// 第一個參數: 監聽的事件類型(event type)
// 第二個參數: 事件被觸發時,要執行的 callback function
// 第三個參數: options 是一個物件,可控制的屬性有 capture、once...等
addEventListener(type, listener, options)
divs.forEach(div => div.addEventListener('click', logText, {
// 預設為false,表示事件的觸發順序為冒泡階段(由下往上的層級)
// 若爲 true,則表示設定為捕獲階段(由上往下的層級。印出:one,two,three)
capture: false,
//預設為 false,若設爲 true,則表示事件只監聽一次
//執行後 removeEventListener
once: false
//預設為 false,若設爲 true,則表示將無法在函式中使用 event.preventDefault() 方法。
passive: false
}));
step 4 : stopPropagation()
e.stopPropagation
:表示此處監聽到事件後,停止事件以捕獲或者冒泡的方式往下個層級傳遞,
function logText(e) {
console.log(this.classList.value);
e.stopPropagation(); // stop bubbling or capture
}
補充: Event delegation
如果有很多類似的監聽事件,與其在每個元素中挂上監聽,較好的做法是統一監聽在這些元素的父元素
參考資料:
- EventTarget: addEventListener() method@MDN
- W3C-Document Object Model Events-Phases@w3.org
- Event: stopPropagation() method
- JavaScript Event Capture, Propagation and Bubbling - #JavaScript30 25/30 @Wes Bos
- [ Alex 宅幹嘛 ] 👨💻 深入淺出 Javascript30 快速導覽 | Day 24:Sticky Nav @Alex 宅幹嘛
- 25 - Event Capture, Propagation, Bubbling and Once @guahsu
- 25 - Event Capture, Propagation, Bubbling and Once@dusin
- 介紹 DOM 及事件流程