第 8 章:事件處理 (Handling Events)
在前面的章節中,我們已經簡單地使用了一些事件處理,例如按鈕的 onClick
事件。在這一章中,我們將深入學習 React 中的事件系統,了解如何有效地處理使用者互動,以及如何在不同場景下編寫優雅的事件處理程式碼。
8.1 React 事件系統概述
React 實現了自己的事件系統,稱為「合成事件」(SyntheticEvents)。這個系統提供了跨瀏覽器的一致性,並且與原生 DOM 事件保持相容性。
8.1.1 合成事件 (SyntheticEvents)
什麼是合成事件?
合成事件是 React 對原生 DOM 事件的包裝,它具有以下特點:
- 跨瀏覽器相容性:在所有瀏覽器中提供一致的行為
- 與原生事件相同的介面:具有與原生事件相同的方法和屬性
- 效能優化:React 使用事件委託來處理事件,提高效能
- 預設行為控制:可以使用
preventDefault()
和stopPropagation()
基本語法:
function Button() {
const handleClick = (event) => {
console.log('按鈕被點擊了!');
console.log('事件型別:', event.type);
console.log('目標元素:', event.target);
};
return <button onClick={handleClick}>點擊我</button>;
}
8.2 常見的事件類型
8.2.1 滑鼠事件
import React, { useState } from 'react';
function MouseEvents() {
const [message, setMessage] = useState('');
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleClick = (e) => {
setMessage(`按鈕在 (${e.clientX}, ${e.clientY}) 被點擊`);
};
const handleDoubleClick = () => {
setMessage('按鈕被雙擊了!');
};
const handleMouseEnter = () => {
setMessage('滑鼠進入按鈕區域');
};
const handleMouseLeave = () => {
setMessage('滑鼠離開按鈕區域');
};
const handleMouseMove = (e) => {
setPosition({ x: e.clientX, y: e.clientY });
};
const handleContextMenu = (e) => {
e.preventDefault(); // 阻止預設的右鍵選單
setMessage('右鍵被點擊!');
};
return (
<div>
<h3>滑鼠事件範例</h3>
<button
onClick={handleClick}
onDoubleClick={handleDoubleClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onContextMenu={handleContextMenu}
style={{
padding: '10px 20px',
margin: '10px',
backgroundColor: '#4CAF50',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
互動按鈕
</button>
<div
onMouseMove={handleMouseMove}
style={{
width: '300px',
height: '200px',
border: '2px dashed #ccc',
margin: '10px',
padding: '10px'
}}
>
<p>在這個區域移動滑鼠</p>
<p>滑鼠位置: ({position.x}, {position.y})</p>
</div>
<p>訊息: {message}</p>
</div>
);
}
export default MouseEvents;
8.2.2 鍵盤事件
import React, { useState } from 'react';
function KeyboardEvents() {
const [inputValue, setInputValue] = useState('');
const [keyInfo, setKeyInfo] = useState('');
const [items, setItems] = useState([]);
const handleKeyDown = (e) => {
setKeyInfo(`按下: ${e.key} (代碼: ${e.keyCode})`);
// 處理特殊按鍵
if (e.key === 'Enter') {
e.preventDefault();
if (inputValue.trim()) {
setItems([...items, inputValue.trim()]);
setInputValue('');
}
} else if (e.key === 'Escape') {
setInputValue('');
setKeyInfo('輸入已清除');
}
};
const handleKeyUp = (e) => {
if (e.key !== 'Enter' && e.key !== 'Escape') {
setKeyInfo(`放開: ${e.key}`);
}
};
const handleChange = (e) => {
setInputValue(e.target.value);
};
return (
<div>
<h3>鍵盤事件範例</h3>
<div>
<input
type="text"
value={inputValue}
onChange={handleChange}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
placeholder="輸入文字,按 Enter 添加項目,Esc 清除"
style={{
padding: '8px',
width: '300px',
marginBottom: '10px'
}}
/>
<p>鍵盤資訊: {keyInfo}</p>
</div>
<div>
<h4>項目列表:</h4>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
</div>
);
}
export default KeyboardEvents;
8.3 事件處理的最佳實踐
8.3.1 事件處理函式的定義方式
1. 在元件內部定義:
function Component() {
const handleClick = () => {
console.log('按鈕被點擊');
};
return <button onClick={handleClick}>點擊</button>;
}
2. 使用 useCallback 優化:
import React, { useCallback, useState } from 'react';
function OptimizedComponent({ onDataChange }) {
const [count, setCount] = useState(0);
// 使用 useCallback 來避免不必要的重新渲染
const handleIncrement = useCallback(() => {
setCount(prev => prev + 1);
}, []);
const handleDataSubmit = useCallback((data) => {
onDataChange(data);
}, [onDataChange]);
return (
<div>
<p>計數: {count}</p>
<button onClick={handleIncrement}>增加</button>
</div>
);
}
8.4 總結
事件處理是 React 應用程式中使用者互動的核心機制。
本章重點:
- 合成事件系統:React 提供跨瀏覽器相容的事件處理
- 常見事件類型:滑鼠、鍵盤、表單事件的處理方法
- 最佳實踐:使用 useCallback、正確傳遞參數、防抖節流
- 效能優化:事件委託和其他優化技術
關鍵要點:
- 使用合成事件:利用 React 的事件系統獲得一致性和效能
- 正確處理表單:使用
preventDefault()
控制預設行為 - 優化事件處理函式:使用
useCallback
避免不必要的重新渲染 - 處理頻繁事件:使用防抖和節流技術
掌握事件處理對於建立互動性強的 React 應用程式至關重要。在下一章中,我們將學習條件渲染和列表渲染,進一步增強我們對 React 渲染機制的理解。