美文网首页react
react的合成事件

react的合成事件

作者: xiaohesong | 来源:发表于2019-04-24 15:04 被阅读1次

如果各位看了react的源码,会发现在事件处理的代码里,有那么一段注释:

/**
 * Summary of `ReactBrowserEventEmitter` event handling:
 *
 *  - Top-level delegation is used to trap most native browser events. This
 *    may only occur in the main thread and is the responsibility of
 *    ReactDOMEventListener, which is injected and can therefore support
 *    pluggable event sources. This is the only work that occurs in the main
 *    thread.
 *
 *  - We normalize and de-duplicate events to account for browser quirks. This
 *    may be done in the worker thread.
 *
 *  - Forward these native events (with the associated top-level type used to
 *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want
 *    to extract any synthetic events.
 *
 *  - The `EventPluginHub` will then process each event by annotating them with
 *    "dispatches", a sequence of listeners and IDs that care about that event.
 *
 *  - The `EventPluginHub` then dispatches the events.
 *
 * Overview of React and the event system:
 *
 * +------------+    .
 * |    DOM     |    .
 * +------------+    .
 *       |           .
 *       v           .
 * +------------+    .
 * | ReactEvent |    .
 * |  Listener  |    .
 * +------------+    .                         +-----------+
 *       |           .               +--------+|SimpleEvent|
 *       |           .               |         |Plugin     |
 * +-----|------+    .               v         +-----------+
 * |     |      |    .    +--------------+                    +------------+
 * |     +-----------.--->|EventPluginHub|                    |    Event   |
 * |            |    .    |              |     +-----------+  | Propagators|
 * | ReactEvent |    .    |              |     |TapEvent   |  |------------|
 * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|
 * |            |    .    |              |     +-----------+  |  utilities |
 * |     +-----------.--->|              |                    +------------+
 * |     |      |    .    +--------------+
 * +-----|------+    .                ^        +-----------+
 *       |           .                |        |Enter/Leave|
 *       +           .                +-------+|Plugin     |
 * +-------------+   .                         +-----------+
 * | application |   .
 * |-------------|   .
 * |             |   .
 * |             |   .
 * +-------------+   .
 *                   .
 *    React Core     .  General Purpose Event Plugin System
 */

下面就来说说这个。如果图片更直接,那么就来看看这个图片:


react event

可以发现,和上面注释里没啥区别。

来一步步的解析,让这货更明朗起来。

Top-level delegation is used to trap most native browser events. This may only occur in the main thread and is the responsibility of
ReactDOMEventListener, which is injected and can therefore support
pluggable event sources. This is the only work that occurs in the main thread.

React为每个事件类型使用一个事件侦听器来调用虚拟DOM中所有提交的处理程序。看看下面的这个例子:

const ExampleComponent = () => (
  <div onClick={onClick}>
    <div onClick={onClick} />
  </div>
)

这样我们就将在原生DOM上为click事件注册一个事件侦听器。我们在Chrome开发工具上运行getEventListeners(document.querySelector('button'))方法,我们将得到类似的以下结果:

{click: Array(n)} //n is number

每个事件类型的监听器都会在每个渲染周期中得到保证,所以如果我们定义额外的keydown类型的事件处理程序,我们会得到如下输出:

{click: Array(n), keydown: Array(1)}

We normalize and de-duplicate events to account for browser quirks. This may be done in the worker thread.

对于每个浏览器,无论其实现如何,都将拥有一致的事件参数,因为React将它们规范化。
由于 React 为多个处理程序注册了单个事件侦听器, 因此它需要为每个处理程序重新分配事件。

Forward these native events (with the associated top-level type used to trap it) to EventPluginHub, which in turn will ask plugins if they want to extract any synthetic events.

EventPluginHub是React事件处理系统中的一个非常核心的组件。这就是将所有事件插件统一到一个位置的方法,并将被分派的事件重定向到每个事件。每个插件负责提取和处理不同的事件类型,例如,有SimpleEventPlugin来处理可能在大多数浏览器中实现的事件,比如鼠标事件和按键(源码); 还有ChangeEventPlugin,它就是处理大家都知道的onChange事件(源码)。

合成事件是React的规范化事件参数,它确保所有浏览器之间的一致性,并由插件生成。注意,合成事件正在被合并!这意味着相同的对象实例在多个处理程序中使用,只是在每次调用前都使用新属性重置它,然后处理:

function onClick(event) {
  console.log(event); // => nullified object.
  console.log(event.type); // => "click"
  const eventType = event.type; // => "click"
  setTimeout(function() {
    console.log(event.type); // => null
    console.log(eventType); // => "click"
  }, 0);
  // Won't work. this.state.clickEvent will only contain null values.
  this.setState({clickEvent: event});
  // You can still export event properties.
  this.setState({eventType: event.type});
}

The EventPluginHub will then process each event by annotating them with "dispatches", a sequence of listeners and IDs that care about that event.

前面也提到了,每个事件都可以有多个处理程序,即使每个处理程序实际上都被真正的 DOM 侦听一次。因此, 需要累积由事件处理程序及其相应的fiber节点(虚拟 DOM 树中的节点)组成的相关 "调度", 以便后面的使用。

The EventPluginHub then dispatches the events.

插件遍历之前累积的信息并调度事件,从而调用提交的事件处理程序。

本文就说了那么多,但是有几点希望你可以知道:

  • 注册到主DOM (window.document)的顶级事件监听器也可以注册到其他DOM,这取决于应用程序容器的位置。比如,容器被iframe采用,那么iframe的DOM将是主要的事件监听器; 它也可以是一个文档片段、一个shadow DOM 等。重要的是,你应该意识到这一点,并知道事件的传播有这小小的限制。
  • React将事件重新调度分为两个阶段: 一个用于捕获,另一个用于冒泡,就像原生DOM那样。
  • 为React Native完成的事件处理与React DOM不同,你不应该混淆这两者! React只是一个库,它生成我们想要呈现的视图的虚拟表示,React DOM/Native是React和我们使用的环境之间的桥梁。(对于这个,可以参考这个地方)。本文仅与React DOM相关!

本文原文

相关文章

  • react事件机制

    (1)react合成事件 react合成事件执行过程: 合成事件与原生事件的区别 1. 写法不同,合适事件是驼峰写...

  • react-原生事件和合成事件的区别

    react-原生事件和合成事件的区别及源码分析 概念 关于 react 合成事件 目的: 封装事件,实现跨平台,把...

  • React学习之漫谈React

    事件系统 合成事件的绑定方式 Test 合成事件的实现机制:事件委派和自动绑定。 React合成事件系统的委托机制...

  • react 事件机制

    一、合成事件 react 基于 vitrual dom 实现了 syntheticEvent (合成事件),rea...

  • React -------合成事件和DOM原生事件混用须知

    React合成事件和DOM原生事件混用须知

  • React-阻止事件冒泡

    react中分为合成事件、原生事件 合成事件:在jsx中直接绑定的事件,如 原生事件:通过js原生代码绑定的事件,...

  • React的事件

    React事件系统 事件处理程序通过 合成事件(SyntheticEvent)的实例传递,SyntheticEve...

  • React的合成事件

    React的合成事件:React中声明的事件最终只绑定在document节点上, 通过事件代理的方式来实现事件的操...

  • react冷门小知识 - 未完待续

    1. react合成事件 SyntheticEvent(React 17和老版本对比) React 17 以前 R...

  • js函数防抖、节流实现

    React中使用防抖函数和节流函数 在React事件调用时,React传递给事件处理程序是一个合成事件对象的实例。...

网友评论

    本文标题:react的合成事件

    本文链接:https://www.haomeiwen.com/subject/uufggqtx.html