解析addEventListener中事件的捕捉、傳遞、氣泡與單次執行方法
首先建立三層DIV作為稍後測試使用的模型, 依序包覆為:紫色>淺橘色>深橘色
<div class="one">
<div class="two">
<div class="three">
</div>
</div>
</div>接著建立click事件
// 取得頁面的所有div
const divs = document.querySelectorAll('div');
function logText(e) {
// 印出當前div的class name
console.log(this.classList.value);
}
// 為每個div加上click事件監聽
divs.forEach(div => div.addEventListener('click', logText));當對著畫面中間(深橘色/one)做點擊時,console印出來的是
three
two
one會從click的位置的最深處開始向外層連動所有的divclick事件,像是氣泡一樣的從內向外浮出去。
深入檢查,會發現其實addEventListener是有第三個參數的:
divs.forEach(div => div.addEventListener('click', logText, {
capture: false, // 預設為false
}));第三個參數的第一個屬性Capture就是事件的捕捉順序,
剛剛提到click後console印出來順序是由內向外,
若將Capture設為true會在點擊中間(深橘色/one)會印出:
one就只有印出one而已,這是因為對當前最外層的容器one去點了,
就已經捕捉到目的了,所以他不會再往下找,只會到點擊的最外層目標為止。
但如果想從內層往外層點,而且是依選取層印出對應層級的話,
就要在列印的function加上topPropagation()來使用:
function logText(e) {
console.log(this.classList.value);
e.stopPropagation(); // stop bubbling!
}這會使原本向外延伸的氣泡事件停止。
而addEventListener的第三參數還有一個新屬性once,
新增一個按鈕的click事件來測試:
button.addEventListener('click', () => {
console.log('Click!!!');
}, {
once: true
});它可以使這個按鈕click被執行結束後,直接unbind這個元素與事件,
之後這個按鈕就已經不會再被觸發click事件了!
可以運用在很多避免重複點擊的狀況,例如表單送出後禁止user重複點擊。
在一開始的練習JavaScript練習-臺北市旅遊景點時也有記錄到這個第三參數,
但當時只知道capture並不曉得once,對於整體的事件捕捉也不是很清楚,
經由這個練習範例加深了這個印象,雖然目前還是沒有正式運用到,
但這個觀念記著不吃虧,之後遇到相關問題會有更多可以思考的腦中資料:)。