react合成事件
React 合成事件是 React 自己实现的一套事件系统,它是对浏览器原生事件 (Native Event) 的一层封装。
为什么react要自己在封装原生的事件系统呢?
解决浏览器兼容性问题
不同浏览器对事件的实现存在差异。例如:
- 获取事件目标:IE 中是 event.srcElement,而标准浏览器是 event.target。
- 阻止事件冒泡:IE 中是 event.cancelBubble = true,而标准浏览器是 event.stopPropagation()。
提升性能和管理效率
在传统的 Web 开发中,如果页面上有大量的元素需要绑定事件(比如一个巨大的列表),为每个 DOM 元素都添加一个事件监听器会占用大量内存,并可能影响性能。
React 采用了一种更高效的模式:事件委托 (Event Delegation) 。
| 特性 | 传统方式 (为每个 item 绑定) | React 方式 (事件委托) |
|---|---|---|
| 真实监听器数量 | 1000 个 | 1 个 (针对 click 事件) |
| 监听器位置 | 每个 | 应用的根节点上 |
| 内存占用 | 高 | 极低 |
| 初始性能 | 较慢 (需要执行 1000 次绑定) | 极快 (只需执行 1 次绑定) |
| 动态内容管理 | 复杂 (需要手动为新增元素绑定/解绑) | 自动 (新增的 li 无需任何操作,点击时事件依然能被根节点捕获并正确处理) |
react阻止事件传递的原理
function App() {
const handleParentClick = () => {
console.log('Parent Div clicked');
};
const handleChildClick = (e) => {
console.log('Child Button clicked');
// 我们在这里调用 stopPropagation
e.stopPropagation();
};
return (
<div onClick={handleParentClick} style={{ padding: '20px', border: '1px solid red' }}>
<button onClick={handleChildClick}>Click Me</button>
</div>
);
}
当你点击 "Click Me" 按钮时,会发生以下事情:
-
**原生冒泡 (不受影响)**:浏览器的原生 click 事件从 触发,然后冒泡到,再到 ,最后到应用的根节点。这个过程没有被阻止。 -
React 监听到事件:在根节点,React 的监听器被触发。它检查原生事件的 target,发现是那个 。
-
React 开始分发:React 开始了它的“模拟冒泡”之旅。
-
第一站:按钮组件。React 找到了与 对应的 onClick 处理器,也就是 handleChildClick。
-
执行 handleChildClick:
- console.log('Child Button clicked'); 被执行,你在控制台看到了 "Child Button clicked"。
- e.stopPropagation() 被调用。
-
-
stopPropagation 的魔法:当 e.stopPropagation() 被调用时,React 会在这个合成事件对象 e 上设置一个内部标志,比如 isPropagationStopped = true。
-
React 停止分发:
- handleChildClick 执行完毕后,React 的分发器准备继续向上“冒泡”到父级 。
- 在调用 handleParentClick 之前,分发器会检查合成事件对象 e 上的 isPropagationStopped 标志。
- 它发现这个标志是 true!
- 因此,React 决定不再继续向上分发事件。handleParentClick 函数永远不会被调用。
- handleChildClick 执行完毕后,React 的分发器准备继续向上“冒泡”到父级