今天沒有要做作品,而是認識一下 DOM 元素的 event bubbling & event capturing
Event Bubbling 也就是冒泡事件,這也是事件監聽的預設方式(另一種是 Event Capturing,等等會介紹)
從 HTML 可以看到共有三個區塊元素,div.one
在最外面,依序包覆 div.two
以及 div.three
,如果將三個元素都設定監聽事件並點擊最裡面的 div.three
並印出 this.classList.value
,你覺得結果會是什麼?
function logText() {
console.log(this.classList.value);
}
div.forEach(div => div.addEventListener('click', logText));
// 點擊 div.three 後
// three
// two
// one
結果 three
、two
、one
依序被印出,而這就是 Event Bubbling;會有這轉現象產生是因為當最裡面的 three
被點擊時,會如同漣漪一般由內至外擴散到父層容器,並一路直達最外層(也就是 body
,但由於 body
沒有設定監聽事件,所以不會看到 console 印出來)
相對於 bubbling 是由內至外,capturing 則是由外至內的發生,但首先我們要先設定 capturing
設定的方式有兩種,一種是在監聽事件的第三個參數帶入 true
(而 false
就是 bubbling 了!)
div.forEach(div => div.addEventListener('click', logText, true));
另一種方法是在第三個參數帶入一個 object,並指定屬性 capture: true
div.forEach(div => div.addEventListener('click', logText, {capture: true}));
這時再點擊 three
,會發現觸發順序變了!
// 點擊 three 後
// one
// two
// three
變成由最外層先被觸發了而不是剛剛的最內層 three
,這就是 Event Capturing
簡單來說 bubbling 就是由內而外,而 capturing 則是由外至內
如果要避免 bubbling & capturing 的發生,可以在 callback 中寫入 event.stopPropagation()
,禁止 bubbling 或是 capturing 的發生
function logText(e) {
e.stopPropagation();
console.log(this.classList.value);
}
div.forEach(div => div.addEventListener('click', logText));
現在點擊時,只會看到當前點擊的元素了,而不會 bubblng 至父層;而當設定 capturing 時,每次點擊都會是 one
,這也是因為禁止 capturing,所以觸發事件只會在最外層發生
once
:只監聽一次的事件最後要介紹的是 once
,一個可以放在監聽事件中的屬性。它的功能是只會監聽一次事件,當觸發並執行 callback 後就不再被觸發,可以想成是事件觸發一次後執行 removeEventListener(..)
的感覺
這裡的範例是 HTML 最下方的元素 button
,我們加入 once
屬性
button.addEventListener('click', logText, {capture: false, once: true});
當點擊按鈕時,只有第一次會印出 button
,之後不管你按得多猛烈都不會有效果
今天介紹就到這裡,謝謝收看!