event 事件系统初始化
1 )概述
- react事件系统比较的复杂,它是基于dom的事件系统
- 在dom事件系统上面进行了一个深度的封装
- 它里面的很多实现逻辑都是自由的一套
- 在初始化 react-dom 的源码的时候,会为react的事件系统注入 reactdom 相关的一些插件
- 因为react事件系统,它有一个独立的模块,这个模块是一个公用性质的模块
- 就是说它是可以给 react-dom 用,也可以给 react-native 用
- 不同平台它们的事件系统可能会不一样,这个时候就对于不同的平台
- 它们要去使用同一个 event 模块的时候,使用注入的方式来注入一些跟平台相关的逻辑在里面
- 在这个模块,也是有一部分核心的内容是全平台通用的,这部分内容是react抽象出来的
- 我们关注平台插件注入的一个流程,以及它插入之后到底做了什么事情
- 首先要确定一个插件注入的顺序
- 因为在react当中它的插件执行是会按照顺序来的
- 如果不按顺序来,可能会出现一定的问题
- 然后要注入插件模块
- 最后要计算 registationNameModules 等属性
- 首先要确定一个插件注入的顺序
- 在之前 completeWork 的时候,初始化 dom 节点的时候
- 要去绑定 props 对应的 dom 的 attributes 的时候
- 就有遇到过这个 registationNameModules 属性
2 )源码
定位到 packages/react-dom/src/client/ReactDOM.js#L20
import './ReactDOMClientInjection';
再次定位到 packages/react-dom/src/client/ReactDOMClientInjection.js
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as EventPluginHub from 'events/EventPluginHub';
import * as EventPluginUtils from 'events/EventPluginUtils';
import {
getFiberCurrentPropsFromNode,
getInstanceFromNode,
getNodeFromInstance,
} from './ReactDOMComponentTree';
import BeforeInputEventPlugin from '../events/BeforeInputEventPlugin';
import ChangeEventPlugin from '../events/ChangeEventPlugin';
import DOMEventPluginOrder from '../events/DOMEventPluginOrder';
import EnterLeaveEventPlugin from '../events/EnterLeaveEventPlugin';
import SelectEventPlugin from '../events/SelectEventPlugin';
import SimpleEventPlugin from '../events/SimpleEventPlugin';
/**
* Inject modules for resolving DOM hierarchy and plugin ordering.
*/
EventPluginHub.injection.injectEventPluginOrder(DOMEventPluginOrder);
EventPluginUtils.setComponentTree(
getFiberCurrentPropsFromNode,
getInstanceFromNode,
getNodeFromInstance,
);
/**
* Some important event plugins included by default (without having to require
* them).
*/
EventPluginHub.injection.injectEventPluginsByName({
SimpleEventPlugin: SimpleEventPlugin,
EnterLeaveEventPlugin: EnterLeaveEventPlugin,
ChangeEventPlugin: ChangeEventPlugin,
SelectEventPlugin: SelectEventPlugin,
BeforeInputEventPlugin: BeforeInputEventPlugin,
});
-
看到它 import 了一大堆的东西,后续只是调用了3个方法
injectEventPluginOrder
setComponentTree
这个先跳过injectEventPluginsByName
-
看下
EventPluginHub.injection.injectEventPluginOrder(DOMEventPluginOrder);
- 这个
DOMEventPluginOrder
// packages/react-dom/src/events/DOMEventPluginOrder.js const DOMEventPluginOrder = [ 'ResponderEventPlugin', 'SimpleEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin', ]; export default DOMEventPluginOrder;
- 它单纯的 export 出来了一个数组
- 这个数组可以看到有6项,每一项都以一个 Plugin 为结尾的
- 这些 plugin 都是在 react-dom 这个环境当中要用到的 plugin
- 这边只是用来定义这些 plugin 它的一个顺序
- 这个
-
后续
EventPluginHub.injection.injectEventPluginsByName
这个方法的参数- 发现这里少了一个
ResponderEventPlugin
先不管
- 发现这里少了一个
-
关注下
EventPluginHub
这个模块下的 injection/** * Methods for injecting dependencies. */ export const injection = { /** * @param {array} InjectedEventPluginOrder * @public */ injectEventPluginOrder, /** * @param {object} injectedNamesToPlugins Map from names to plugin modules. */ injectEventPluginsByName, };
- 上述内部这两个方法来自
./EventPluginRegistry.js
进入/** * Injects an ordering of plugins (by plugin name). This allows the ordering * to be decoupled from injection of the actual plugins so that ordering is * always deterministic regardless of packaging, on-the-fly injection, etc. * * @param {array} InjectedEventPluginOrder * @internal * @see {EventPluginHub.injection.injectEventPluginOrder} */ export function injectEventPluginOrder( injectedEventPluginOrder: EventPluginOrder, ): void { invariant( !eventPluginOrder, 'EventPluginRegistry: Cannot i
- 上述内部这两个方法来自