跳到主要内容

认识

一、认识


React基于浏览器的事件机制自身实现了一套事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等。在React 中这套事件机制被称之为合成事件。**React 事件系统**分为三个部分:

  • 第一部分: 是事件合成系统,初始化会注册不同的事件插件

  • 第二部分: 是在一次渲染过程中,对事件标签中事件的收集,向 container 注册事件

  • 第三部分: 就是一次用户交互,事件触发,到事件执行一系列过程

二、模拟事件


React.js 为什么要模拟事件呢?

  1. 兼容性跨平台: 对于不同的浏览器,对事件存在不同的兼容性。React 通过顶层事件代理机制,保证冒泡的统一性,抹平不同浏览器事件对象之间的差异,将不同平台的事件进行模拟成合成事件,使其能够跨浏览器执行

  2. 避免垃圾回收: 在实际中,我们的事件会被频繁的创建和回收,这样会影响其性能,为了解决这个问题,React引入事件池,通过事件池来获取和释放事件。也就是说,所有的事件并不会被释放,而是存入到一个数组中,如果这个事件触发,则直接在这个数组中弹出即可,这样就避免了频繁创建和销毁

  3. 将所有事件统一管理: 在原生事件中,所有的事件都绑定在对应的 Dom 上,如果页面复杂,绑定的事件会非常多,这样就会造成一些不可控的问题。而 React 将所有的事件都放在了 Document 上,这样就可以对事件进行统一管理,从而避免一些不必要的麻烦

三、事件合成


3.1 什么是事件合成?

React 事件不是绑定在对应元素上的, 而是统一绑定在顶部容器上, 使用一个统一的事件去监听。在 React.js 17.x 之前是绑定在 document 上的,在 React.js 17.x 改成了 app 容器上。React 应用中, 元素绑定的事件并不是原生事件,而是 React 合成的事件,比如 onClick 是由 click 合成,onChange 是由 blurchangefocus 等多个事件合成。

四、插件机制


React 中, 首先对于不同的事件,有不同的处理逻辑, 对应的事件源对象也有所不同,React 的事件和事件源是自己合成的,所以对于不同事件需要不同的事件插件处理。

registrationNameModules 记录了 React 事件(比如 onBlur )和与之对应的处理插件的映射。比如下面的 onClick ,就会用 SimpleEventPlugin 插件处理,onChange 就会用 ChangeEventPlugin 处理。应用于事件触发阶段,根据不同事件使用不同的插件。

const registrationNameModules = {
onBlur: SimpleEventPlugin,
onClick: SimpleEventPlugin,
onClickCapture: SimpleEventPlugin,
onChange: ChangeEventPlugin,
onChangeCapture: ChangeEventPlugin,
onMouseEnter: EnterLeaveEventPlugin,
onMouseLeave: EnterLeaveEventPlugin,
...
}

registrationNameDependencies 对象保存了 React 事件和原生事件对应关系, 在事件绑定阶段,如果发现有 React 事件,比如 onChange ,就会找到对应的原生事件数组,逐一绑定。

{
onBlur: ['blur'],
onClick: ['click'],
onClickCapture: ['click'],
onChange: ['blur', 'change', 'click', 'focus', 'input', 'keydown', 'keyup', 'selectionchange'],
onMouseEnter: ['mouseout', 'mouseover'],
onMouseLeave: ['mouseout', 'mouseover'],
}

参考资料


「React进阶」一文吃透react事件原理