DOM事件處理
DOM(Document Object Model)
- HTML的程式介面,是網頁與使用者互動的重要部分
- 提供了文件以擁有屬性與函式的節點與物件組成的結構化表示
- 每一個節點皆為物件(Object)且擁有各自的屬性以及方法,允許在JavaScript當中操作HTML元素
事件處理
說明
- 通常是由使用者的操作行為產生(例如:滑鼠點擊、鍵盤輸入...)
- 當某個事件在某個元素上發生時,可以撰寫JS做出對應的動作
方法
- addEventListener : 新增事件監聽
- removeEventListener : 移除事件監聽
const btn = document.getElementById("myButton");const myAlert = () => { alert('Hello Event!')}// 新增事件監聽btn.addEventListener("click", myAlert)// 移除事件監聽btn.removeEventListener('click', myAlert)
事件傳遞機制
事件流
- 捕獲階段(Capture Phase):
- 事件從根節點向目標元素傳播,過程中觸發個別元素的捕獲階段事件監聽
- 目標階段(Target Phase)
- 事件達到目標元素
- 冒泡階段(Bubbling Phase)
- 事件從目標元素回到根節點,過程中觸發個別元素的冒泡階段事件監聽
先捕獲,後冒泡
指定階段觸發
- 可以使用 addEventListener 的第三個參數來指定事件處理函數在哪個階段應該被觸發
- 使用 true 或 {capture: true}: 將在捕獲階段觸發
- 使用 false 或 {capture: false}: 將在冒泡階段觸發
- 不加入參數,預設為 false ,事件處理會在冒泡階段觸發
// 在冒泡階段觸發(預設)element.addEventListener('click', function() { console.log('Bubbling phase');});// 在捕獲階段觸發element.addEventListener('click', function() { console.log('Capture phase');}, true);
事件冒泡問題
- 當在冒泡階段時,事件從目標元素向上冒泡至根元素,並觸發所經過元素的事件監聽
- 過程中可能會觸發非目標元素的事件,發生非預期行為
範例
HTML結構
<div id="parent"> <button id="child">Click!</button></div>
JavaScript程式碼
document.getElementById('child').addEventListener('click', function() { alert('Child Button Clicked!');});document.getElementById('parent').addEventListener('click', function() { alert('Parent Div Clicked!');});
點擊 "Click!" 按鈕時
- 先看到 "Child Button Clicked!"
- 然後會是 "Parent Div Clicked!" (不需要觸發的事件)
取消事件傳遞
event.stopPropagation()
- 阻止事件繼續冒泡或捕獲,但不會阻止同一個元素上的其他事件監聽器被觸發
<div id="parent"> <button id="child">Click Me!</button> </div>
// 第二個監聽器(`Second Listener: This will still fire.`)仍然會被觸發document.getElementById('child').addEventListener('click', function(event) { alert('First Listener: Child Button Clicked!'); event.stopPropagation();});document.getElementById('child').addEventListener('click', function() { alert('Second Listener: This will still fire.');});document.getElementById('parent').addEventListener('click', function() { alert('Parent Div Clicked!'); // This will not be triggered});
event.stopImmediatePropagation()
- 除了阻止事件繼續冒泡或捕獲,還會阻止同一個元素上的其他事件監聽器被觸發
//只會觸發'First Listener: Child Button Clicked!'document.getElementById('child').addEventListener('click', function(event) { alert('First Listener: Child Button Clicked!'); event.stopImmediatePropagation();});document.getElementById('child').addEventListener('click', function() { alert('Second Listener: This will not fire.');});document.getElementById('parent').addEventListener('click', function() { alert('Parent Div Clicked!'); // This will not be triggered});
事件委派 ( Event Delegation)
- 利用事件冒泡的特性,可以只新增事件監聽器到父元素,處理多個子元素的事件
- 減少監聽器數量, 讓程式碼更有效率
範例
- 使用 event.target ,可以判斷哪個子元素被點擊
document.getElementById('parent').addEventListener('click', function(event) { if(event.target.id === 'child') { alert('Child Button Clicked through Delegation!'); }});
參考資料
# JavaScript