合成事件
react18 事件机制
参考 https://juejin.cn/post/7191308289177550906#heading-2
<div ref={parentRef} onClick={parentBubble} onClickCapture={parentCapture}>
<button ref={childRef} onClick={childBubble} onClickCapture={childCapture}>
点击
</button>
</div>
上面代码层级如下 document -> root -> div -> button
- document 注册的事件最先触发
- root 注册的事件触发,React 根据当前点击的 event.target 收集对应 DOM 节点的 fiber 节点中的 pendingProps,pendingProps 在这里简单理解就是 jsx 中 DOM 节点对应的 props,收集 props 中的 onClickCapture(因为触发的是点击事件,所以收集 onClickCapture 捕获函数),最终在队列中收集成 [childCapture, parentCapture],然后倒序触发
- div 注册的捕获事件触发
- p 注册的捕获事件触发
- p 注册的冒泡事件触发
- div 注册的冒泡事件触发
- root 收集的队列里有两个冒泡事件, [childBubble, parentBubble], 然后正序触发
- document 注册的冒泡事件触发
react 17 合成事件机制
其实 React 的事件机制就是一个典型的事件代理,将所有 DOM 节点的事件代理到根节点上统筹处理,基本原理如下:
- 初始化根节点,在根节点上绑定原生事件的监听器并分配优先级
- React 渲染过程中收集事件
- 渲染完成后调度真实事件的调用
源码执行过程如下:
- 执行
dispatchEvent
- 创建事件对应的合成事件
SyntheticEvent
- 收集捕获的回调函数和对应的节点实例
- 收集冒泡的回调函数和对应的节点实例
- 执行对应的回调函数,同时将
SyntheticEvent
作为参数传入
完整示例
比如我们在 react 中触发一次 click 事件
<div>
<button onClick={handerClick}>点击</button>
</div>
button 对应一个 Fiber Node,在 memoizedProps
上挂载事件
memoizedProps = {
onClick: handerClick,
}
【待续】
和 react 16 对比
- react16 事件池
- 批量更新