- react自身实现了一套自己的事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等
- react 的所有事件并没有绑定到具体的dom节点上而是绑定在了document 上 (React 17 之后是绑定在 #root 节点上),然后由统一的事件处理程序来处理,同时也是基于浏览器的事件机制(冒泡),所有节点的事件都会在 document 上触发。
- React 根据W3C规定来定义自己的系统,其事件被称之为 合成事件(SyntheticEvent).
- 自定义事件的动机:
- 抹平不同浏览器之间的兼容性差异。【主要动机】
- 事件合成,即事件自定义。 事件合成机可以处理兼容性问题,也可以用来自定义事件。
- 提供一个抽象跨平台机制。类似 Virtual DOM 抽象了跨平台的渲染方式,合成事件提供了一个抽象的跨平台事件机制。
- 可以做更多的优化。例如 利用 事件委托机制,几乎所有事件的触发都代理到了document。
- 可以干预事件的分发。V16 引入 Fiber 架构,React 可以通过干预事件的芬达来优化用户的交互体验
-
原生事件阻止冒泡肯定会阻止合成事件的触发。合成事件的阻止冒泡不会影响原生事件。
- 原生事件是被绑定在目标元素本身的,其执行是在 目标阶段执行。
- 合成事件的触发是基于浏览器的事件机制来实现的,通过冒泡机制冒泡到最顶层元素,然后再由
dispatchEvent
统一去处理。 其执行是在 冒泡阶段。 - 因此如果原生事件阻止了冒泡,那么就不会有之后 合成事件的执行了。
- React 拿到将要挂载的组件的虚拟 dom,然后处理
react dom
的 props ,判断属性内是否声明事件的属性,比如onClick,onChange
, 得到事件类型click,change
和 对应的事件处理程序后,执行后面3步
- 完成 事件注册【组件挂载阶段,根据组件内的声明的事件类型-onclick,onchange 等,给 document 上添加事件 -addEventListener,并指定统一的事件处理程序 dispatchEvent】
- 将
react dom
,事件类型,处理函数fn
放入数组存储 - 组件挂载完成后,处理 b 步骤生成的数组,经过遍历把事件处理函数存储到
listenerBank 中【所有事件统一的存放到一个对象里,缓存起来,为了在触发事件的时候可以查找到对应的方法去执行】
- react 里所有事件的触发都是通过
dispatchEvent
方法统一进行派发的,而不是在注册的时候直接注册声明的回调。React
把所有的事件和事件类型以及react 组件进行关联,把这个关系保存在了一个map
里,也就是一个对象里(键值对),然后在事件触发的时候去根据当前的组件id
和事件类
型查找到对应的事件fn
。