React 事件處理與事件傳遞:一篇搞懂冒泡、捕獲與阻止事件!
前言:
在開發React 時,「事件」是我們最常打交道的部分之一。無論是點擊按鈕、提交表單,還是操作其他互動元素,都需要處理事件。如果你剛接觸 React,可能會有以下疑問:
為什麼點擊按鈕時會觸發父層的事件?
什麼是事件的「冒泡」和「捕獲」?
如何攔截事件傳播或避免預設行為?
這篇文章將帶你從零開始理解 React 的事件處理,並解釋事件傳遞的原理及其在開發中的實際應用場景。
React 的事件處理基礎
什麼是事件?
根據 @MDN Web Docs - Introduction to events 對於事件的定義,事件是瀏覽器用來回應用戶操作的一種訊號。例如當你點擊按鈕、鍵入文字、或滑動滑鼠時,瀏覽器都會生成一個事件並傳遞給應用程式進行處理。
常見的事件類型包括:
滑鼠事件(Mouse Events):click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout
鍵盤事件(Keyboard Events):keydown, keyup, keypress
表單事件(Form Events):submit, change, input, focus, blur
在 JavaScript 中,事件本身是一個由瀏覽器產生的事件物件(Event Object),它記錄了與互動相關的所有資訊,例如觸發的 HTML 元素、滑鼠座標、鍵盤按鍵等。
讓我們看看事件物件的基本樣貌和幾個常用屬性:
document.querySelector('button').addEventListener('click', (event) => { console.log(event.type); // 事件類型,例如 "click" console.log(event.target); // 觸發事件的 DOM 元素 console.log(event.currentTarget); // 綁定事件的 DOM 元素 console.log(event.clientX, event.clientY); // 滑鼠的 X、Y 座標});
HTML/JS 的事件處理方式
在早期的網頁開發中,事件處理主要有以下幾種方式:
內聯屬性(Inline Attributes)
直接在 HTML 元素上綁定事件處理邏輯,這種方式直觀但不推薦,因為不易維護。
使用 DOM 的 addEventListener
更現代且推薦的方式是使用 JavaScript 的 addEventListener,可以將事件邏輯與 HTML 結構分離,提升可讀性和重用性。
const button = document.querySelector('button');button.addEventListener('click', () => { alert('Hello!');});
React 的事件處理方式
React 的事件處理與原生 HTML 有顯著的不同,主要表現在以下幾點:
使用合成事件(Synthetic Event)
在 React 中,事件處理是基於一種叫做 合成事件(Synthetic Event) 的機制。合成事件是一層跨瀏覽器的事件封裝,提供了一個一致的介面。React 不會直接將事件綁定到每個 DOM 元素,而是採用事件委派的方式,將所有事件統一綁定到根節點(例如 document 或 root 元素)。
這樣做的好處是:
跨瀏覽器兼容性:自動處理不同瀏覽器之間的事件差異。
效能提升:React 使用事件委派機制,將所有事件綁定在根元素上,減少 DOM 操作。
function handleClick(event) { console.log(event.type); // "click"}
駝峰式命名
在 React 中,事件屬性使用駝峰式命名(Camel Case),例如 onClick、onMouseOver。
事件處理程式是函式引用
React 要求事件處理程式是函式的引用,而不是直接執行結果。這樣可以避免函式在渲染時被過早執行。
錯誤示範:
function handleClick() { alert('點擊了');} // handleClick 立即執行,錯誤!
正確寫法:
什麼是事件傳遞?捕獲與冒泡解讀
在 JavaScript 事件模型中,當事件觸發時,並不僅僅作用於目標元素本身,還會按照一個固定的順序傳遞。這種事件傳遞機制分為兩個主要階段:捕獲階段 和 冒泡階段。
事件傳遞的階段
事件在傳遞過程中會經歷以下三個階段:
捕獲階段(Capture Phase)
從 window 開始,沿著 DOM 樹向下傳遞到事件的目標元素。
目標階段(Target Phase)
事件到達目標元素,並執行與該元素相關的事件處理程式。
冒泡階段(Bubble Phase)
從目標元素開始,沿著 DOM 樹向上傳遞到 window。
這樣的流程讓開發者可以在事件傳遞的不同階段執行邏輯。
冒泡階段(Bubble Phase)
冒泡指的是事件從目標元素向其祖先元素傳遞,直至 window 為止。當需要在父層統一處理子層的邏輯時,冒泡階段非常有用。
警告React 默認只處理冒泡階段的事件,
範例:父元素捕獲子元素的點擊事件
function handleParentClick(event) { console.log('父層事件觸發'); console.log('點擊的子元素是:', event.target);}
輸出結果:
當點擊「按鈕 1」時,event.target 是