事件冒泡 (Event Bubbling) & 事件捕獲 (Event Capturing)
前言
在 2018 iT 邦幫忙鐵人賽,看到 Kuro 大的重新認識 JavaScript 系列文,仔細的閱讀後,紀錄自己觀念不足的部份,也非常推薦給大家觀看此系列文。
事件冒泡 (Event Bubbling)
事件冒泡指的是「從啟動事件的元素節點開始,逐層往上傳遞」,直到整個網頁的根節點,也就是 document。
事件捕獲 (Event Capturing)
剛剛說過「事件冒泡」機制是由下往上來傳遞,那麼「事件捕獲」(Event Capturing) 機制則正好相反。
事件傳遞順序
既然事件傳遞順序有兩種機制,那我怎麼知道事件是依賴哪種機制執行的?
答案是:兩種都會執行。
事件機制的原理
事件監聽 EventTarget.addEventListener()
addEventListener() 基本上有三個參數,分別依序是
- 事件名稱
- 事件的處理器(事件觸發時執行的 function)
- Boolean,由這個 Boolean 決定事件是以「捕獲」或「冒泡」機制執行,若不指定則預設為「冒泡」。
1 | <button id="btn">Click</button> |
1 | var btn = document.getElementById("btn"); |
使用這種方式來註冊事件的好處是可以重複指定多個「處理器」(handler) 給同一個元素的同一個事件:
1 | var btn = document.getElementById("btn"); |
點擊後 console 出現:
1 | "HI"; |
若是要解除事件的註冊,則是透過 removeEventListener() 來取消。
removeEventListener() 的三個參數與 addEventListener() 一樣,分別是「事件名稱」、「事件的處理器」以及「捕獲」或「冒泡」的機制。
但是需要注意的是,由於 addEventListener() 可以同時針對某個事件綁定多個 handler,所以透過 removeEventListener() 解除事件的時候,第二個參數的 handler 必須要與先前在 addEventListener() 綁定的 handler 是同一個「實體(記憶體位址) 」。
1 | var btn = document.getElementById("btn"); |
像上面這樣,即使執行了 removeEventListener 來移除事件,但 click 時仍會出現 ‘HI’。 因為 addEventListener 與 removeEventListener 所移除的 handler 實際上是兩個不同實體(記憶體位址) 的 function 物件。
1 | var btn = document.getElementById("btn"); |