combobox 如何 不触发 onchange事件_React事件机制原理

本文深入探讨React事件机制,解释了为何原生事件阻止冒泡会阻止合成事件触发,以及React事件注册、存储、执行的过程。通过源码解析,展示了React如何通过事件委托减少内存消耗,提高性能,并处理兼容性问题。
摘要由CSDN通过智能技术生成

初步理解

表象理解

先回顾一下 React 事件机制基本理解,React 自身实现了一套自己的事件机制,包括事件注册、事件合成、事件冒泡、事件派发等,虽然和原生是两码事,但是也是基于浏览器的事件机制下完成的。

我们都知道 React 的所有事件并没有绑定到具体的 DOM 节点,而是绑定到 document 上,然后由统一的事件处理程序来处理,同时也是基于浏览器的事件机制(冒泡),所有节点的时间都会在 document 上触发。

试想一下

如果一个节点同时绑定了合成和原生事件,那么禁止冒泡后执行关系是怎样?

因为合成事件的触发是基于浏览器的事件机制来实现的,通过冒泡机制冒泡到最顶层元素,然后再由 dispatchEvent 统一去处理。

得出结论

原生事件阻止冒泡肯定会组织合成事件的触发,合成事件的阻止冒泡不会影响原生事件。

原因在于,浏览器的事件执行机制是执行在前,冒泡在后,所以在原生事件中阻止冒泡会阻止合成事件的执行,反之不成立。

综上,两者最好不要一起使用,避免出现一些奇怪的问题。

意义

React 将事件全部统一交给 document 来委托处理的原因是:

  1. 减少内存消耗,提高性能,不需要注册那么多的事件,一种事件只需要在 document 上注册一次即可
  2. 统一规范,用于解决兼容性问题,简化事件逻辑
  3. 对开发者更加友好

对合成的理解

既然我们对 React 的事件机制有了初步的了解,那么可以知道合成事件并不是简单的合成和处理,从广义上还包括:

  • 对原生事件的封装
  • 对某些原生事件的升级和改造
  • 不同浏览器事件的兼容处理

对原生事件的封装

56740fe046089c10c0f5179c1da4fa84.png
img

上面的代码是个一个元素添加点击事件的回调函数,方法中的参数 e 其实并不是原生事件中的 event,而是 React 包装过的对象,同时原生事件中的 event 被放在了这个对象的 nativeEvent 字段。

0cc20bfc9341339cc7fc58b5677beb02.png
img

再看下官网文档

0f94ef1faa4e30457239988db71e8867.png
img

SyntheticEvent 是 React 合成事件的基类,定义了合成事件的基础公共属性和方法。

React 会根据当前的事件类型来使用不同的合成事件对象,比如鼠标:点击事件 -- SyntheticMouseEvent,焦点事件 -- SyntheticFocusEvent 等,但都是继承与 SyntheticEvent。

aaf49cc909ab5644ccb8863d7a9fd727.png
img
9be506d43416135d61d1f92269082b03.png
img
472fe0ca941f5c7717453bfb286fada7.png
img

对原生事件的升级和改造

对于有些 DOM 元素事件,我们进行事件绑定之后,Reacgt 并不是只处理你生命的事件类型,还会额外增加一些其他的事件,帮助我们提升交互和体验。

比如说:

当我们给 input 生命一个 onChange 事件,React 帮我们做了很多工作:

fe18800de33d3e487783f4d7453e4bad.png
img

可以看到 React 不只是帮助我们注册一个 onchange 事件,还注册了很多其他的事件。

而这时候我们向文本框输入内容的时候,是可以实时得到内容,

然而原生事件只注册了一个 onchange 的话,需要在失去焦点的时候才能触发这个事件,这个缺陷 React 帮我们弥补了。

ps:图中有一个 invalid 事件是注册在当前元素而非在 document 的,可能是因为这个事件是 HTML5 表单属性特有的,需要在输入框输入的时候进行校验,如果是放到 document 上就不会生效了。

浏览器的兼容处理

react 在给 document 注册事件的时候也是做了兼容性处理的。

d382282306849fb74a6ee28267e2c19f.png
img

上面这个代码就可以看出,在给 document 注册事件的时候,内部也同时对 IE 浏览器做了兼容处理。

事件注册机制

大致流程

React 事件注册其实主要做了两件事情:

  • 事件注册:组件挂载阶段,根据组件内声明的事件类型:onclick、onchange 等,给 document 添加事件监听,并制定统一的事件处理程序 dispatchEvent;
  • 事件存储:就是把 React 组件内所有事件统一存放到一个对象内,缓存起来,为了在触发事件的时候能够找到对应的方法去执行。
79b1926946df28a44a40d095aa567607.png
img

关键步骤

首先 React 拿到将要挂载在组件的虚拟 DOM(React Element 对象)&#x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值