React 事件系统介绍及源码分析

举个例子

你们在使用 React 的过程当中应该都写过相似这样的代码:数组

若是 list 有 1000 项怎么办呢?浏览器

React 事件系统

几个关键概念

概念 操做 优势
事件委托 几乎将全部事件都委托到 document 减小内存占用和避免频繁的操做DOM
合成事件 对原生 DOM事件对象的封装 全部浏览器中都表现一致,实现了跨浏览器兼容
对象池 利用对象池来管理合成事件对象的建立和销毁 便于统一管理;能够减小垃圾回收和新建对象过程当中内存的分配操做,提升了性能
  • 对象池是什么? 对象池其实就是一个集合,里面包含了咱们须要的对象集合,这些对象都被对象池所管理,若是须要这样的对象,从池子里取出来就行,可是用完须要归还。缓存

  • 何时使用对象池? 初始化、实例化的代价高,且有需求须要常常实例化,但每次实例化的数量又比较少的状况下,使用对象池能够得到显著的效能提高。异步

大致流程

事件注册事件触发事件清理函数

源码分析

以开头的例子为示例代码进行分析。源码分析

1.事件注册性能

咱们写在 li 元素属性上的事件监听函数最终是怎么绑定到原生 DOM 上的?(如下为部分节选代码spa

事件注册入口

肯定事件最终注册到哪

  • 利用了事件委托,几乎全部的事件最终都会被委托到 document 或者 Fragment 上。

获取原生 DOM 事件名和绑定事件的方式

绑定冒泡阶段的事件监听函数

2.事件触发3d

点击 li 元素后,发生了什么,事件监听函数是如何被调用的?cdn

事件执行入口

2.1 生成合成事件

从对象池中取出合成事件

  • React 事件系统的一大亮点,它将全部的合成事件都缓存在 对象池 中,能够大大下降对象的建立和销毁的时间,提高性能。

模拟捕获和冒泡

  • 生成合成事件以后,会调用 accumulateTwoPhaseDispatches(event),该方法最终会调用 traverseTwoPhase。

  • 模拟过程当中会把全部事件监听函数及其对应的节点都加入到 event(合成事件) 的属性中。

2.2 执行事件

按序执行和清理事件

  • 这也就是为何当咱们在须要异步读取操做一个合成事件对象的时候,须要执行 event.persist(),否则 React 就会在这里释放掉这个事件。

回调函数真正被执行

  • React 在收集回调数组的时候并不会去管咱们是否调用了 stopPropagation ,而是会在事件执行的阶段才会去检查是否须要中止冒泡。

3.事件清理 事件执行完以后是如何清理的?

再来举个🌰

1. 当 React 事件和原生事件混用时的阻止冒泡

  • 在 React 事件系统 中调用 e.stopPropagation() 能够阻止 React 的合成事件以及绑定在 window 上的原生事件;

  • 在原生事件 中调用 e.stopPropagation(),若是是在 document 以前,那么全部的 React 事件都会被阻止。

1.点击 button 以后,输出结果是什么?(ABCDE排序)

2.分别把 (1) 和 (2) 的 e.stopPropagation() 加上,输出结果又是什么?(ABCDE排序)

2.异步方式访问事件

有一个模糊搜索框,为了不频繁的发送请求,利用 setTimeout 加了 200 毫秒延时。

相关文章
相关标签/搜索