====== 第七章:事件处理 ======
===== 7.1 React 事件系统 =====
React 实现了一个合成事件系统(SyntheticEvent),它是浏览器原生事件的跨浏览器包装器。
**与原生事件的区别**:
* 命名使用 camelCase:onClick 而非 onclick
* 使用 JSX 表达式传入函数:onClick={handleClick} 而非 onClick="handleClick()"
* 不能通过 return false 阻止默认行为,必须显式调用 preventDefault
**示例**:
// HTML
// React
**阻止默认行为**:
// HTML
链接
// React
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('链接被点击');
}
return (
点击我
);
}
===== 7.2 类组件中的事件绑定 =====
**绑定 this 的方法**:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// 方法 1:在构造函数中绑定
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
);
}
}
**其他绑定方法**:
class Toggle extends React.Component {
state = { isToggleOn: true };
// 方法 2:使用类属性语法(推荐)
handleClick = () => {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
};
// 方法 3:在 render 中使用箭头函数(不推荐,每次渲染都创建新函数)
render() {
return (
);
}
}
===== 7.3 向事件处理函数传递参数 =====
class List extends React.Component {
handleClick = (id, event) => {
console.log('ID:', id);
console.log('Event:', event);
};
render() {
return (
{this.props.items.map(item => (
// 方法 1:箭头函数
- this.handleClick(item.id, e)}>
{item.name}
// 方法 2:bind(事件对象会自动传递)
-
{item.name}
))}
);
}
}
===== 7.4 常用事件 =====
**鼠标事件**:
function MouseEvents() {
const handleClick = () => console.log('点击');
const handleDoubleClick = () => console.log('双击');
const handleMouseEnter = () => console.log('鼠标进入');
const handleMouseLeave = () => console.log('鼠标离开');
const handleMouseMove = (e) => console.log('移动:', e.clientX, e.clientY);
const handleContextMenu = (e) => {
e.preventDefault();
console.log('右键菜单');
};
return (
鼠标事件区域
);
}
**键盘事件**:
function KeyboardEvents() {
const handleKeyDown = (e) => {
console.log('按下:', e.key, '键码:', e.keyCode);
if (e.key === 'Enter') {
console.log('回车键');
}
if (e.ctrlKey && e.key === 's') {
e.preventDefault();
console.log('Ctrl+S');
}
};
const handleKeyUp = (e) => {
console.log('释放:', e.key);
};
return (
);
}
**表单事件**:
function FormEvents() {
const handleChange = (e) => {
console.log('值变化:', e.target.value);
};
const handleFocus = () => console.log('获得焦点');
const handleBlur = () => console.log('失去焦点');
const handleInput = (e) => console.log('输入:', e.target.value);
return (
);
}
**焦点事件**:
function FocusEvents() {
const handleFocus = (e) => {
console.log('焦点在:', e.target.name);
};
const handleBlur = (e) => {
console.log('离开:', e.target.name);
};
return (
);
}
===== 7.5 事件对象 =====
React 的合成事件对象(SyntheticEvent)是对原生事件的跨浏览器包装。
**常用属性**:
* boolean bubbles
* boolean cancelable
* DOMEventTarget currentTarget
* boolean defaultPrevented
* number eventPhase
* boolean isTrusted
* DOMEventTarget target
* number timeStamp
* string type
**常用方法**:
* preventDefault() - 阻止默认行为
* stopPropagation() - 阻止事件冒泡
* persist() - React 17+ 已不需要,事件对象现在是持久的
function EventDemo() {
const handleClick = (e) => {
console.log('事件类型:', e.type);
console.log('目标元素:', e.target);
console.log('当前元素:', e.currentTarget);
console.log('时间戳:', e.timeStamp);
e.preventDefault(); // 阻止默认行为
e.stopPropagation(); // 阻止冒泡
};
return 点击;
}
===== 7.6 事件委托 =====
React 使用事件委托机制,所有事件都被委托到 document 或应用根容器(React 17+)。
**优点**:
* 减少内存消耗(不需要为每个元素绑定事件)
* 动态添加的元素自动有事件处理
**注意**:
* 事件处理函数中的 event.target 是实际触发事件的元素
* event.currentTarget 是绑定事件处理函数的元素
===== 7.7 表单处理 =====
**受控组件**:
function NameForm() {
const [value, setValue] = useState('');
const handleChange = (e) => {
setValue(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
alert('提交的名字: ' + value);
};
return (
);
}
**textarea**:
// HTML 中 textarea 的值通过子元素设置
// React 中通过 value 属性设置
function EssayForm() {
const [value, setValue] = useState('请撰写关于你喜欢的事物的文章');
return (
**select**:
function FlavorForm() {
const [value, setValue] = useState('coconut');
return (
);
}
**处理多个输入**:
function ReservationForm() {
const [state, setState] = useState({
isGoing: true,
numberOfGuests: 2
});
const handleChange = (e) => {
const { name, type, checked, value } = e.target;
setState({
...state,
[name]: type === 'checkbox' ? checked : value
});
};
return (
);
}
**非受控组件**:
function NameForm() {
const inputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
alert('Name: ' + inputRef.current.value);
};
return (
);
}
===== 7.8 事件性能优化 =====
**使用 useCallback 缓存事件处理函数**:
import { useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
// 每次渲染都创建新函数
const handleClick1 = () => {
setCount(c => c + 1);
};
// 只在依赖变化时创建新函数
const handleClick2 = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
);
}
**避免在 render 中创建新函数**:
// 不推荐
function List({ items }) {
return (
{items.map(item => (
- handleClick(item.id)} // 每次渲染都创建新函数
/>
))}
);
}
// 推荐
function List({ items }) {
return (
);
}
function ItemContainer({ item }) {
const handleClick = useCallback(() => {
// 处理点击
}, [item.id]);
return ;
}
===== 7.9 总结 =====
本章详细介绍了 React 的事件处理:
* 合成事件系统
* 事件绑定和 this 处理
* 常用事件类型
* 表单处理(受控和非受控组件)
* 事件委托机制
* 事件性能优化
事件处理是 React 开发的基础,掌握这些知识对于构建交互式应用至关重要。