React 基于 Virtual DOM 实现了一个 SyntheticEvent(合成事件)层,我们所定义的事件处理器会接收到一个 SyntheticEvent 对象的实例。所有事件都自动绑定到最外层上。如果需要访问原生事件对象,可以使用 nativeEvent 属性。

实现机制

在 React 底层,主要对合成事件做了两件事:事件委派和自动绑定。

事件委派

从 v17.0.0 开始,React 不会将事件处理添加到 document 上,而是将事件处理添加到渲染 React 树的根 DOM 容器中。

react_17_delegation

当组件挂载或卸载时,只是在这个统一的事件监听器上插入或删除一些对象;当事件发生时,首先被这个统一的事件监听器处理,然后在映射里找到真正的事件处理函数并调用。这样做简化了事件处理和回收机制,效率也有很大提升。

自动绑定

在 React 组件中,每个方法的上下文都会指向该组件的实例,即自动绑定 this 为当前组件。而且 React 还会对这种引用进行缓存,以达到 CPU 和内存的最优化。在使用 ES6 classes 或者纯函数时,这种自动绑定就不复存在了,我们需要手动实现 this 的绑定,否则 this 会被定义成 undefined。

绑定 this 的几个方法: 1. bind 方法 2. 构造器内声明 3. 箭头函数

React 合成事件与 JavaScript 原生事件

  1. 事件传播与阻止事件传播

    DOM 事件传播有三个阶段:事件捕获阶段,目标对象的时间处理以及事件冒泡。而 React 的合成事件则没有实现事件捕获,仅仅支持事件冒泡机制。

  2. 事件类型

    React 合成事件的事件类型是 JavaScript 原生事件类型的一个子集。

  3. 事件绑定方式

    React 事件使用驼峰法命名,而不是小写。传递函数作为事件处理,而不是字符串。典型例子如下:

    <!-- 原生 -->
    <button onclick="handleEvent()">Click Me</button>
    
    <!-- React -->
    <button onClick="{handleEvent}">Click Me</button>
    
  4. 事件对象

    React 合成事件系统中,不存在兼容性问题,在事件处理函数中可以得到一个合成事件对象。

参考链接