JS 基礎篇 (10) Event Listeners
事件偵聽
如果要在網頁上與使用者互動時,必須在對應的元素上綁定事件偵聽 addEventListener 函式。
1 | const parent = document.querySelector('.parent'); |
addEventListener() 基本上有三個參數,分別是「事件名稱」、「事件的處理器」(事件觸發時執行的 function),以及一個「Boolean」值,由這個 Boolean 決定事件是以「捕獲」或「冒泡」機制執行,若不指定則預設為「冒泡」。
事件捕獲與冒泡
JS 觸發事件的流程可以分為兩個機制:
- 事件冒泡 (Event Bubbling)
- 事件捕獲 (Event Capturing)
事件冒泡 (Event Bubbling)
事件冒泡指的是「從啟動事件的元素節點開始,逐層往上傳遞」,直到整個網頁的根節點,也就是 document。
事件捕獲 (Event Capturing)
事件捕獲是由上往下傳遞,從document 到 html 到body 最後元素本身。
既然事件傳遞順序有兩種機制,那我怎麼知道事件是依賴哪種機制執行的?
答案是兩種都會觸發,如下圖:
當 td 的 click 事件發生時,會先走紅色的 「capture phase」,上而下依序觸發它們的 click 事件。然後再繼續執行綠色的 「bubble phase」,反方向由
阻止事件傳遞
現在我們知道事件的傳遞流程會先經由捕獲機制再到冒泡機制,若想阻止事件的傳遞,可用 stopPropagation。
1 | const grantParent = document.querySelector('.grantParent'); |
如上我們在 parent 的事件綁定上增加 e.stopPropagation() ,來阻止事件往上層 grantParent 傳遞。
只觸發一次事件
若想限制事件只觸發一次,可以將 once 參數設為 true
1 | const child = document.querySelector('.child'); |
解除事件偵聽
若要取消事件偵聽,可以用 removeEventListener(),要注意的是取消偵聽的函式必須是同一個,所以函式要單獨宣告。
1 | const child = document.querySelector('.child'); |
事件指派
當網頁上的元素會動態新增或刪除時,若想對動態增減的元素做事件偵聽,可以用事件指派的方式。
- 事件指派(event delegation): 在外層元素做事件綁定,利用事件捕獲往下傳遞的機制,來選擇觸發事件的目標。
1 |
|
如上,在外層 container 做事件偵聽,當點擊到的是 div 時才處發函式。
Handler 中的 event
當監聽事件發生,透過 addEventListner 會去觸發註冊的 event handler ,也就是指定的函式。
此時 event handler 會去建立一個「事件物件」,裡面包含了與這個事件相關的屬性,並以參數的形式傳給handler。
常用的屬性:
- e.target:触发事件的元素。
- e.currentTarget:当前正在处理事件的元素(即事件处理函数所附加的元素)。
- e.type:事件的类型(例如,”click”、”mouseover” 等)。
- e.preventDefault():阻止事件的默认行为。
- e.stopPropagation():停止事件在 DOM 层次结构中的传播。
- e.target 與 e.currentTarget 差異
1 | <button id="myButton"> |
當今天有一顆按鈕,裡面包有 span、svg 不同元素時
- e.target: 會指向我此時點擊的元素,點到 span 就指向span,點到 svg 就指向 svg
- e.currentTarget: 永遠指向事件綁定的元素。