DOM事件處理

DOM(Document Object Model)

  • HTML的程式介面,是網頁與使用者互動的重要部分
  • 提供了文件以擁有屬性與函式的節點與物件組成的結構化表示
  • 每一個節點皆為物件(Object)且擁有各自的屬性以及方法,允許在JavaScript當中操作HTML元素

DOM Tree

事件處理

說明

  • 通常是由使用者的操作行為產生(例如:滑鼠點擊、鍵盤輸入...)
  • 當某個事件在某個元素上發生時,可以撰寫JS做出對應的動作

方法

  • addEventListener : 新增事件監聽
  • removeEventListener : 移除事件監聽
const btn = document.getElementById("myButton");const myAlert = () => {    alert('Hello Event!')}// 新增事件監聽btn.addEventListener("click", myAlert)// 移除事件監聽btn.removeEventListener('click', myAlert)

事件傳遞機制

事件流

  1. 捕獲階段(Capture Phase):
  • 事件從根節點向目標元素傳播,過程中觸發個別元素的捕獲階段事件監聽
  1. 目標階段(Target Phase)
  • 事件達到目標元素
  1. 冒泡階段(Bubbling Phase)
  • 事件從目標元素回到根節點,過程中觸發個別元素的冒泡階段事件監聽

先捕獲,後冒泡

DOM事件流程

指定階段觸發

  • 可以使用 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!" 按鈕時

  1. 先看到 "Child Button Clicked!"
  2. 然後會是 "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