Jeff的隨手筆記

學習當一個前端工程師

0%

『Day 10』React 的事件處理機制

前言

到目前為止我們討論了 React 元件的各種基礎概念,包括如何建立元件、使用 Props 傳遞資料,以及條件渲染等等。今天讓我們來聊聊在 React 中如何處理使用者的互動 - 也就是事件處理(Event Handling)。

React 的事件處理機制

React 為開發者提供了一種直觀且強大的方式來處理用戶交互。通過在 JSX 中添加事件處理程式,我們可以輕鬆響應各種用戶操作。

最常見的做法是在元件內部定義一個以 “handle” 開頭的函數,然後將其作為 prop 傳遞給相應的 JSX 元素。例

1
2
3
4
5
6
function Button() {
function handleClick() {
alert('點擊了!');
}
return <button onClick={handleClick}>點擊我</button>;
}

也有人會把 handle 寫在後面,這部分只要整份專案統一風格即可:

1
2
3
4
5
6
function Button() {
function clickHandler() {
alert('點擊了!');
}
return <button onClick={clickHandler}>點擊我</button>;
}

注意事項:函式的傳遞方式

在使用事件處理時,有一個非常重要的細節需要注意。我們應該傳遞函式參考,而不是直接呼叫函式:

1
2
3
4
5
// ✅ 正確做法:傳遞函式參考
<button onClick={handleClick}>

// ❌ 錯誤做法:直接呼叫函式
<button onClick={handleClick()}>

這個差異很重要,因為如果直接呼叫函式,React 就無法在適當的時機執行它了。

元件間的事件處理

在實務上,我們經常需要讓父元件指定子元件的事件處理行為。這時候就可以透過 Props 來傳遞事件處理函式。

讓我們來看一個實際的例子,假設我們有一個通用的 Button 元件:

1
2
3
4
5
6
7
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}

這個 Button 元件接受一個 onClick prop,使父元件能夠定義按鈕的點擊行為。現在,我們可以在不同的場景中使用這個按鈕,每次賦予它不同的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function PlayButton({ movieName }) {
function handlePlayClick() {
alert(`播放 ${movieName}!`);
}

return (
<Button onClick={handlePlayClick}>
播放 "{movieName}"
</Button>
);
}

function UploadButton() {
return (
<Button onClick={() => alert('開始上傳!')}>
上傳圖片
</Button>
);
}

PlayButtonUploadButton 都使用了相同的 Button 元件,但賦予了不同的行為。

這種方法的優點是 Button 元件保持了通用性,可以在各種情況下重複使用。

值得注意的是,雖然 HTML 的原生元素(如 <button><div>)在 React 中只能使用標準的瀏覽器事件名稱(如 onClick, onMouseOver),但在創建自定義元件時,我們可以自由命名這些事件處理器屬性。按照慣例,這些屬性通常以 on 開頭,後跟一個大寫字母,但這不是硬性規定。例如:onActivateonSmash 等等。

事件物件與事件冒泡

在 React 中,每當發生使用者互動(像是點擊按鈕、輸入文字等)時,React 會自動建立一個事件物件(通常我們會簡寫為 e 或 event)作為參數,並將它傳給我們的事件處理函式。這個事件物件包含了關於該事件的所有相關資訊,讓我們可以根據需求來運用這些資訊。

認識事件冒泡

讓我們用一個簡單的例子來一起看看:

1
2
3
4
5
6
7
8
function Toolbar() {
return (
<div onClick={() => alert('工具列被點擊了')}>
<button onClick={() => alert('播放!')}>播放影片</button>
<button onClick={() => alert('上傳!')}>上傳圖片</button>
</div>
);
}

如果你點擊其中一個按鈕,你會看到兩個彈跳視窗:

  1. 首先會跳出按鈕本身的訊息(「播放!」或「上傳!」)
  2. 接著會跳出外層工具列的訊息(「工具列被點擊了」)

這就是事件冒泡的效果,事件會從觸發的元素開始,逐層往外傳遞。不過,如果你是直接點擊工具列的空白處,就只會看到「工具列被點擊了」這個訊息。

控制事件傳遞

但有時候我們可能不想要事件繼續往上傳遞,這時候就可以使用事件物件提供的 stopPropagation() 方法:

1
2
3
4
5
6
7
8
9
10
11
function Toolbar() {
return (
<div onClick={() => alert('工具列被點擊了')}>
<button onClick={(e) => {
e.stopPropagation(); // 停止事件冒泡
alert('播放!');
}}>播放影片</button>
<button onClick={() => alert('上傳!')}>上傳圖片</button>
</div>
);
}

在這個例子中,我們使用了 stopPropagation() 來防止事件冒泡。這樣當點擊按鈕時,就不會觸發父層 div 的點擊事件。

處理預設行為

另外,有些 HTML 元素會有預設行為,比如表單提交會導致頁面重新整理。如果想要阻止這種預設行為,可以使用 preventDefault() 方法:

1
2
3
4
5
6
7
<form onSubmit={(e) => {
e.preventDefault();
console.log('表單已送出');
}}>
<button type="submit">送出</button>
</form>

總結

React 的事件處理機制讓我們能夠以直覺且有組織的方式處理使用者互動。透過:

  • 在 JSX 中直接綁定事件處理函式
  • 使用 Props 在元件間傳遞事件處理邏輯
  • 善用事件物件提供的方法來控制事件行為

我們可以建立出互動性更佳的使用者介面。記得在處理事件時要特別注意函式的傳遞方式,以及事件冒泡的機制,這樣才能讓我們的應用程式運作得更加穩定且可預期。