💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

|-----------------------------|
| 💖The Start💖点点关注,收藏不迷路💖 |
📒文章目录
-
- [1. 事件系统基础](#1. 事件系统基础)
-
- [1.1 原生DOM事件的工作原理](#1.1 原生DOM事件的工作原理)
- [1.2 React合成事件(SyntheticEvent)概览](#1.2 React合成事件(SyntheticEvent)概览)
- [2. 核心差异对比](#2. 核心差异对比)
-
- [2.1 事件绑定语法](#2.1 事件绑定语法)
- [2.2 事件传播控制](#2.2 事件传播控制)
- [2.3 事件委托实现](#2.3 事件委托实现)
- [3. 高级特性与陷阱](#3. 高级特性与陷阱)
-
- [3.1 React事件池的注意事项](#3.1 React事件池的注意事项)
- [3.2 混合使用时的冲突](#3.2 混合使用时的冲突)
- [3.3 自定义事件处理](#3.3 自定义事件处理)
- [4. 性能优化实践](#4. 性能优化实践)
-
- [4.1 避免内联函数](#4.1 避免内联函数)
- [4.2 大规模列表优化](#4.2 大规模列表优化)
- [4.3 被动事件监听器](#4.3 被动事件监听器)
- [5. 总结](#5. 总结)

1. 事件系统基础
1.1 原生DOM事件的工作原理
原生DOM事件遵循W3C标准的事件流模型:
javascript
document.getElementById('parent').addEventListener('click', () => {
console.log('捕获阶段');
}, true); // 第三个参数为true表示捕获阶段
document.getElementById('child').addEventListener('click', (event) => {
console.log('目标阶段');
event.stopPropagation(); // 阻止事件冒泡
});
document.getElementById('parent').addEventListener('click', () => {
console.log('冒泡阶段');
});
-
事件对象 包含关键属性:
target
: 触发事件的原始元素currentTarget
: 当前处理事件的元素stopPropagation()
: 停止事件传播
-
绑定方式差异 :
html<!-- 内联方式(不推荐) --> <button onclick="handleClick()">Click</button> <!-- 标准方式 --> <button id="btn">Click</button> <script> document.getElementById('btn').addEventListener('click', handleClick); </script>
1.2 React合成事件(SyntheticEvent)概览
React事件系统的核心设计:
jsx
class MyComponent extends React.Component {
handleClick = (e) => {
console.log(e.nativeEvent); // 访问底层原生事件
e.persist(); // 从事件池中移除该事件对象
}
render() {
return <button onClick={this.handleClick}>Click</button>;
}
}
关键特性:
- 跨浏览器兼容:统一了IE和现代浏览器的事件差异
- 事件池机制 :默认会回收事件对象,异步访问需调用
e.persist()
- 自动绑定this:类组件中无需手动绑定事件处理函数的this指向
2. 核心差异对比
2.1 事件绑定语法
特性 | 原生DOM | React |
---|---|---|
事件名 | onclick |
onClick |
事件值 | 字符串 | 函数引用 |
动态绑定 | 需要手动removeEventListener | 自动处理绑定/解绑 |
错误示例:
jsx
// ❌ 错误:传递的是函数调用结果而非函数引用
<button onClick={handleClick()}>Click</button>
// ✅ 正确
<button onClick={handleClick}>Click</button>
2.2 事件传播控制
捕获阶段处理差异:
javascript
// 原生DOM可监听捕获阶段
div.addEventListener('click', handler, true);
// React需使用特殊属性名
<div onClickCapture={handleCapture}>...</div>
2.3 事件委托实现
原生实现方案:
javascript
document.getElementById('list').addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log('List item clicked:', e.target.dataset.id);
}
});
React的自动委托机制:
- 所有事件默认委托到document节点
- 根据组件树结构自动维护事件映射
- 事件处理器会收到包含组件层级信息的合成事件
3. 高级特性与陷阱
3.1 React事件池的注意事项
典型异步访问问题:
jsx
function handleClick(e) {
setTimeout(() => {
// ❌ 报错:事件属性已被回收
console.log(e.clientX);
// ✅ 解决方案
e.persist();
console.log(e.clientX);
}, 100);
}
3.2 混合使用时的冲突
安全整合第三方库的模式:
jsx
useEffect(() => {
const handleExternalEvent = () => {...};
// 挂载时绑定
externalLib.on('event', handleExternalEvent);
// 卸载时清理
return () => externalLib.off('event', handleExternalEvent);
}, []);
3.3 自定义事件处理
React组件间通信方案:
jsx
// 父组件
<Child onCustomEvent={data => console.log(data)} />
// 子组件
<button onClick={() => props.onCustomEvent(payload)}>
Trigger Event
</button>
4. 性能优化实践
4.1 避免内联函数
优化方案对比:
jsx
// ❌ 每次渲染创建新函数
<button onClick={() => setCount(count + 1)}>+</button>
// ✅ 类组件方案
class Counter extends React.Component {
handleClick = () => {
this.setState(prev => ({ count: prev.count + 1 }));
}
render() {
return <button onClick={this.handleClick}>+</button>;
}
}
// ✅ 函数组件方案
function Counter() {
const handleClick = useCallback(() => {
setCount(prev => prev + 1);
}, []);
return <button onClick={handleClick}>+</button>;
}
4.2 大规模列表优化
虚拟滚动实现要点:
jsx
<FixedSizeList
height={400}
itemCount={1000}
itemSize={50}
>
{({ index, style }) => (
<div style={style} onClick={handleClick}>
Item {index}
</div>
)}
</FixedSizeList>
4.3 被动事件监听器
滚动性能优化方案:
javascript
useEffect(() => {
const opts = { passive: true };
window.addEventListener('scroll', handleScroll, opts);
return () => window.removeEventListener('scroll', handleScroll, opts);
}, []);
5. 总结
关键差异总结表:
维度 | 原生事件 | React合成事件 |
---|---|---|
事件命名 | 全小写 | 驼峰命名 |
事件绑定 | 命令式API | 声明式JSX |
事件对象 | 原生Event | SyntheticEvent |
事件委托 | 需手动实现 | 自动全局委托 |
性能优化 | 需手动管理监听器 | 自动处理大部分场景 |
选型建议:
- 使用原生事件的场景:
- 需要精确控制事件捕获阶段
- 需要处理React未封装的特殊事件(如resizeObserver)
- 性能敏感的底层交互(如游戏循环)
最佳实践:
- 优先使用React的事件系统
- 避免在render中创建新的事件处理器
- 及时清理手动添加的原生事件监听器
- 善用事件委托处理动态内容
🔥🔥🔥道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
|-----------------------------|
| 💖The Start💖点点关注,收藏不迷路💖 |
width="100%">
💖The Start💖点点关注,收藏不迷路💖