combobox 如何 不触发 onchange事件_React 事件系统工作原理

ea7b2fcfffe89f4607cc01af2c326641.png

本文作者: 江水[1]

前言

React 为我们提供了一套虚拟的事件系统,这套虚拟事件系统是如何工作的,笔者对源码做了一次梳理,整理了下面的文档供大家参考。

在 React事件介绍[2] 中介绍了合成事件对象以及为什么提供合成事件对象,主要原因是因为 React 想实现一个全浏览器的框架, 为了实现这种目标就需要提供全浏览器一致性的事件系统,以此抹平不同浏览器的差异。

合成事件对象很有意思,一开始听名字会觉得很奇怪,看到英文名更奇怪 SyntheticEvent, 实际上合成事件的意思就是使用原生事件合成一个 React 事件, 例如使用原生click事件合成了onClick事件,使用原生mouseout事件合成了onMouseLeave事件,原生事件和合成事件类型大部分都是一一对应,只有涉及到兼容性问题时我们才需要使用不对应的事件合成。合成事件并不是 React 的首创,在 iOS 上遇到的 300ms 问题而引入的 fastclick 就使用了 touch 事件合成了 click 事件,也算一种合成事件的应用。

了解了 React 事件是合成事件之后我们看待事件的角度就会有所不同, 例如我们经常在代码中写的这种代码


  Activate Lasers

我们已经知道这个onClick只是一个合成事件而不是原生事件, 那这段时间究竟发生了什么?原生事件和合成事件是如何对应起来的?

上面的代码看起来很简洁,实际上 React 事件系统工作机制比起上面要复杂的多,脏活累活全都在底层处理了, 简直框架劳模。其工作原理大体上分为两个阶段

  1. 事件绑定
  2. 事件触发

下面就一起来看下这两个阶段究竟是如何工作的, 这里主要从源码层分析,并以 16.13 源码中内容为基准。

1. React 是如何绑定事件的 ?

React 既然提供了合成事件,就需要知道合成事件与原生事件是如何对应起来的,这个对应关系存放在 React 事件插件中EventPlugin, 事件插件可以认为是 React 将不同的合成事件处理函数封装成了一个模块,每个模块只处理自己对应的合成事件,这样不同类型的事件种类就可以在代码上解耦,例如针对onChange事件有一个单独的LegacyChangeEventPlugin插件来处理,针对onMouseEnter,  onMouseLeave 使用 LegacyEnterLeaveEventPlugin 插件来处理。

为了知道合成事件与原生事件的对应关系,React 在一开始就将事件插件全部加载进来, 这部分逻辑在 ReactDOMClientInjection[3] 代码如下

injectEventPluginsByName({
     
    SimpleEventPlugin: LegacySimpleEventPlugin,
    EnterLeaveEventPlugin: LegacyEnterLeaveEventPlugin,
    ChangeEventPlugin: LegacyChangeEventPlugin,
    SelectEventPlugin: LegacySelectEventPlugin,
    BeforeInputEventPlugin: LegacyBeforeInputEventPlugin
});

注册完上述插件后, EventPluginRegistry[4] (老版本代码里这个模块唤作EventPluginHub)这个模块里就初始化好了一些全局对象,有几个对象比较重要,可以单独说一下。

第一个对象是 registrationNameModule, 它包含了 React 事件到它对应的 plugin 的映射, 大致长下面这样,它包含了 React 所支持的所有事件类型,这个对象最大的作用是判断一个组件的 prop 是否是事件类型,这在处理原生组件的 props 时候将会用到,如果一个 prop 在这个对象中才会被当做事件处理。

{
     
    onBlur: SimpleEventPlugin,
    onClick: SimpleEventPlugin,
    onClickCapture: SimpleEventPlugin,
    onChange: ChangeEventPlugin,
    onChangeCapture: ChangeEventPlugin,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值