Skip to main content

合成事件

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 节点的事件代理到根节点上统筹处理,基本原理如下:

  1. 初始化根节点,在根节点上绑定原生事件的监听器并分配优先级
  2. React 渲染过程中收集事件
  3. 渲染完成后调度真实事件的调用

源码执行过程如下:

  1. 执行 dispatchEvent
  2. 创建事件对应的合成事件 SyntheticEvent
  3. 收集捕获的回调函数和对应的节点实例
  4. 收集冒泡的回调函数和对应的节点实例
  5. 执行对应的回调函数,同时将 SyntheticEvent 作为参数传入

完整示例

比如我们在 react 中触发一次 click 事件

<div>
<button onClick={handerClick}>点击</button>
</div>

button 对应一个 Fiber Node,在 memoizedProps 上挂载事件

memoizedProps = {
onClick: handerClick,
}

【待续】

和 react 16 对比

  • react16 事件池
  • 批量更新