Open creamidea opened 2 years ago
listenToAllSupportedEvents 会把所有的事件都在 container 上注册一遍!!!
dispatchEventForPluginEventSystem(
domEventName, // 原生事件名称
eventSystemFlags, // 事件标志,比如是否 capture
nativeEvent, // 原生事件对象
return_targetInst, // null, Suspense, HostRoot。后面也被定义为 ancestorInst
targetContainer, // 根 DOM 容器
);
onSelect, onChange 这里事件,会由 SelectEventPlugin.js, ChangeEventPlugin.js 内注册处理。原理:会事先通过 registerEvents 函数注册
function registerEvents() {
registerTwoPhaseEvent('onSelect', [
'focusout',
'contextmenu',
'dragend',
'focusin',
'keydown',
'keyup',
'mousedown',
'mouseup',
'selectionchange',
]);
}
在 extract 阶段,会捕获原生 DOM 事件,比如 mousedown,那么进入 switch-case 进行处理,转成查找注册给 React onSelect 事件
function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) {
...
const listeners = accumulateTwoPhaseListeners(
activeElementInst,
'onSelect',
);
...
}
事件绑定
从 createRoot 函数开始
listenToAllSupportedEvents 进行原生事件绑定。也会处理 nonDelegatedEvents,selectionchange 事件等
addTrappedEventListener 函数根据不同事件,构造不同优先级的处理函数(createEventListenerWrapperWithPriority),得到该函数之后进行原生 DOM 事件绑定,绑定到根 DOM 节点。比如,click 事件,处理函数就是 dispatchDiscreteEvent,默认是 dispatchEvent。并通过 bind 的方式,固定参数:domEventName、eventSystemFlags、targetContainer(即 root dom 节点实例)
至此,绑定原生事件的过程结束,后续就是等待用户交互,触发原生事件,进入诸如 dispatchEvent 函数进行处理。
事件处理
进入诸如 dispatchEvent 函数进行处理。其最总调用 dispatchEventOriginal 函数处理。
blockedOn 有值的 2 种情况,有值则会调用 queueDiscreteEvent 放入到 queuedDiscreteEvents 队列(retryIfBlockedOn 会消费)
dispatchEventsForPlugins 函数就是调用注册的 Plugin 的 extract 方法,提取事件。比如 SimpleEventPlugin.extractEvents 函数内会通过 accumulateSinglePhaseListeners 函数收集绑定的事件,并构造 SyntheticEvent,一起放入到 dispatchQueue 队列
dispatchQueue 队列会在 processDispatchQueue 函数内被处理