本篇文章是基于react 17.0.0-alpha.0版本进行分析
首先要知道,通过react注册的事件大部分并没有被注册到本身节点上,而是统一的注册到了document节点上,目标节点的事件被触时,该事件会冒泡到document上,注册到document的事件回调函数最终会执行到dispatchEvent函数,dispatchEvent函数主要进行事件分发,也就是执行需要执行的回调。
第一个问题:事件处理函数是如何存储的,存储到了什么地方?
事件处理函数是如何存储的这个答案尚未得出,但是从第二个问题的答案可以看出,事件处理函数被存储到了currentTarget[internalEventHandlerListenersKey]上,currentTarget多数情况下都是document节点。
第二个问题:事件被触发时,如何拿到事件目标节点到document节点链路中所有与该事件类型有关的回调函数的?
当事件被触发时,事件会冒泡到document上,document会存在该事件类型的回调,并且只有一个该事件类型的回调。当该回调被触发时,会执行到一个名为dispatchEvent的函数,该函数主要作用是事件分发,或者说是执行所有需要执行的回调。
dispatchEvent:
function dispatchEvent(
domEventName: DOMEventName, // 事件名
eventSystemFlags: EventSystemFlags, // 事件系统标志位
targetContainer: EventTarget, // 事件回调绑定的目标节点
nativeEvent: AnyNativeEvent, // 原生的事件对象) {
...省略
const blockedOn = attemptToDispatchEvent(
domEventName,
eventSystemFlags,
targetContainer,
nativeEvent,
);
...省略
}
可以看到 dispatchEvent内部实际调用了attemptToDispatchEvent来进行事件分发的,接下来看attemptToDispatchEvent的代码
attemptToDispatchEvent:
function attemptToDispatchEvent(
domEventName: DOMEventName,
eventSystemFlags: EventSystemFlags,
targetContainer: EventTarget,
nativeEvent: AnyNativeEvent,
) {
const nativeEventTarget = getEventTarget(nativeEvent); // 真正触发