Skip to main content

Event Bubbling (propagation), Event Capturing

Bubbling​

When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.

從啟動事件的元素節點開始,逐層往上傳遞

Event Capturing​

the event goes down to the element. 從最上層的母元素開始,逐層往下傳遞

Comparison​

alt text

事件兩者都會執行 ,會先執行 Capturing 再執行 Bubbling

當然你可以提供 addEventListener 第二個參數去補抓順序

If it’s false (default), 會被設定為 Bubbling

If it’s true, 會被設定為 Capturing

var btn = document.getElementById('btn');
btn.addEventListener('click', function(){
console.log('HELLO');
}, false ); // Bubbling

若需要取消 Bubbling 也可以使用 event.stopPropagation()

延伸考題: What’s Event Delegation?​

If there are many elements inside one parent, and you want to handle events on them — don’t bind handlers to each element. Instead, bind the single handler to their parent and get the child from e.target

Event Delegation是一種運用 Event Bubbling 概念而能減少監聽器數目的方法,將事件處理器綁在目標元素的父元素上進行處理,可以減少大量子事件監聽器的數量

// Before using delegated event
let elements = document.querySelectorAll('ul > li > a');
for (let elem of elements) {
elem.addEventListener('click', function(e){
console.log(e.target)
// to something
})
}

// Attach a delegated event handler
document.getElementById('list').addEventListener('click', function(e){
if (e.target.tagName == 'a'){
console.log(e.target)
// to something
}
}

// 选择共同的父元素

const list = document.getElementById('list');

// 绑定事件监听器

list.addEventListener('click', function(event) {
// 检查目标元素
if (event.target.tagName === 'LI') {
// 执行相应操作
console.log(event.target.textContent);
}
});

Tree Maps​

alt text

推薦閱讀​

英文: Bubbling and capturing, Event delegation: https://javascript.info/bubbling-and-capturing, https://javascript.info/event-delegation

中文:

重新認識 JavaScript: Day 14 事件機制的原理 、Huli 的 DOM 的事件傳遞機制:捕獲與冒泡 : https://blog.huli.tw/2017/08/27/dom-event-capture-and-propagation/

[Day 17] JS - 冒泡事件 (Event Bubbling): https://ithelp.ithome.com.tw/articles/10265819