在React@17.0.3版本中:
id = root的DOM元素中(网上很多说是在document中,17版本不是了);id = root的DOM元素中触发;React自身实现了一套事件冒泡捕获机制;React实现了合成事件SyntheticEvent;React在17版本不再使用事件池了(网上很多说使用了对象池来管理合成事件对象的创建销毁,那是16版本及之前);id = root的DOM元素中委托,其实是一直在触发的,只是没有绑定对应的回调函数;
盗用一张官方图,按官方解释,之所以会将事件委托从document中移到id = root的DOM元素,是为了可以更加安全地进行新旧版本 React 树的嵌套。
感兴趣的可以访问:React中文网站 。
registerEvents;listenToAllSupportedEvents;SyntheticBaseEvent;dispatchEvent;事件注册是自执行的,也就是React自身进行调用的:
// 注册React事件
registerSimpleEvents();
registerEvents$2();
registerEvents$1();
registerEvents$3();
registerEvents();
React事件就是在组件中调用的onClick这种写法的事件。上面分为5个函数写,主要是区分不同的事件注册逻辑,但是最后都会添加到allNativeEvents的Set数据结构中。
这里会注册大部分事件,它们在React被定义为顶级事件。
它们分为三类:
discreteEvent,常见的如:click, keyup, change;userBlocking,常见的如:dragEnter, mouseMove, scroll;continuous,常见的如:error, progress, load, ;0:离散事件, 1:用户阻塞事件, 2:连续事件
它们会注册冒泡和捕获阶段两个事件。
注册类似onMouseEnter,onMouseLeave单阶段事件,只注册冒泡阶段事件。
注册onChange相关事件,注册冒泡和捕获阶段两个事件。
注册onSelect相关事件,注册冒泡和捕获阶段两个事件。
注册onBeforeInput,onCompositionUpdate等相关事件,注册冒泡和捕获阶段两个事件。
在React源码系列之二:React的渲染机制曾提到过,React在开始渲染前,会为应用创建一个fiberRoot作为应用的根节点。在创建fiberRoot还会做一件事,就是
listenToAllSupportedEvents(rootContainerElement);
从字面就能理解这个函数是做事件监听的,其中rootContainerElement参数就是应用中的id = root的DOM元素。相关参考视频讲解:进入学习
该函数主要遍历上面事件注册添加到allNativeEvents的事件,按照一定规则,区分冒泡阶段,捕获阶段,区分有无副作用进行监听,监听的api还是addEventListener:
// 监听冒泡阶段事件
function addEventBubbleListener(target, eventType, listener) {
target.addEventListener(eventType, listener, false);
return listener;
}
// 监听捕获阶段事件
function addEventCaptureListener(target, eventType, listener