React学习笔记——事件原理

172 阅读2分钟

React 事件处理

React 有一套自己独特的时间系统,实现统一管理,为实现跨浏览器、跨端的兼容处理。

组织冒泡

React 中如果想要阻止事件向上冒泡,可以用 e.stopPropagation() 。

阻止默认行为

React 中用 e.preventDefault() 阻止事件默认行为。

事件系统

React 事件系统可分为三个部分:

  • 第一个部分是事件合成系统,初始化会注册不同的事件插件。
  • 第二个就是在一次渲染过程中,对事件标签中事件的收集,向 container 注册事件
  • 第三个就是一次用户交互,事件触发,到事件执行一系列过程。

事件合成

  • React 的事件不是绑定在元素上的,而是统一绑定在顶部容器上,在 v17 之前是绑定在 document 上的,在 v17 改成了 app 容器上。这样更利于一个 html 下存在多个应用(微前端)。
  • onClick 就会用 SimpleEventPlugin 插件处理,onChange 就会用 ChangeEventPlugin 处理
  • 此外React事件还会对应原生事件,绑定到 document 上的实际是原生事件。
  • 一个react可能对应一个或者多个原生事件。
{
    onBlur: ['blur'],
    onClick: ['click'],
    onClickCapture: ['click'],
    onChange: ['blur', 'change', 'click', 'focus', 'input', 'keydown', 'keyup', 'selectionchange'],
    onMouseEnter: ['mouseout', 'mouseover'],
    onMouseLeave: ['mouseout', 'mouseover'],
    ...
}

事件绑定

对于标签上的事件 onChange 和 onClick 会保存在对应 DOM 元素类型 fiber 对象( hostComponent )的 memoizedProps 属性上,会绑定事件监听器。 绑定在 document 的事件不是我们实际写的handleClick函数,而是 React 统一的事件处理函数 dispatchEvent ,React 需要一个统一流程去代理事件逻辑,包括 React 批量更新等逻辑。

事件触发

一次点击事件的执行

  1. 批量更新
  2. 合成事件源
  3. 形成事件执行队列

在第一步通过原生 DOM 获取到对应的 fiber ,接着会从这个 fiber 向上遍历,遇到元素类型 fiber ,就会收集事件,用一个数组收集事件:

  • 如果遇到捕获阶段事件 onClickCapture ,就会 unshift 放在数组前面。以此模拟事件捕获阶段。
  • 如果遇到冒泡阶段事件 onClick ,就会 push 到数组后面,模拟事件冒泡阶段。
  • 一直收集到最顶端 app ,形成执行队列,在接下来阶段,依次执行队列里面的函数。