开始注册事件
1 2 3 4 5 6 7 SimpleEventPlugin.registerEvents(); EnterLeaveEventPlugin.registerEvents(); ChangeEventPlugin.registerEvents(); SelectEventPlugin.registerEvents(); BeforeInputEventPlugin.registerEvents();
1 2 3 4 5 6 7 allNativeEvent :Set <DOMEventName> = {'click' ,'keyup' ,'keydown' ,...};registrationNameDependencies["onClick" ] = ["click" ]; registrationNameDependencies['onMouseEnter' ] = ['mouseout' , 'mouseover' ]; topLevelEventsToReactNames:Map <DOMEventName,string |null > = {"click" :"onClick" };
大致流程
listenToAllSupportedEvent
非委托事件只有捕获阶段。 而委托事件捕获冒泡都会绑定。
1 2 3 4 5 6 7 8 9 10 11 12 allNativeEvents.forEach(domEventName => { if (domEventName !== 'selectionchange' ) { if (!nonDelegatedEvents.has(domEventName)) { listenToNativeEvent(domEventName, false , rootContainerElement); } listenToNativeEvent(domEventName, true , rootContainerElement); } });
**注意: **selectionChange事件是监听在document上的,因为它不会冒泡。
绑定react的listener到root || document上 listenToNativeEvent –> addTrappedEventListener –> listener = createEventListenerWrapperWithPriority
createEventListenerWrapperWithPriority 这里进行创建listener,listener有如下几种:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 function createEventListenerWrapperWithPriority ( targetContainer: EventTarget, domEventName: DOMEventName, eventSystemFlags: EventSystemFlags, ): Function { const eventPriority = getEventPriority(domEventName); let listenerWrapper; switch (eventPriority) { case DiscreteEventPriority: listenerWrapper = dispatchDiscreteEvent; break ; case ContinuousEventPriority: listenerWrapper = dispatchContinuousEvent; break ; case DefaultEventPriority: default : listenerWrapper = dispatchEvent; break ; } return listenerWrapper.bind( null , domEventName, eventSystemFlags, targetContainer, ); }
这三种listener存在一个优先级的差别。 最终都会调用dispatchEvent.
dispatchEvent
这是react进行触发事件监听函数的地方,这里的listener是绑定到组件props上的事件处理函数。
首先判断是否是allowReplay事件:
1 2 3 4 const allowReplay = (eventSystemFlags & IS_CAPTURE_PHASE) === 0 ;
然后是先去尝试调度事件,判定是否会blockOn:
1 2 3 4 5 6 const blockedOn = attemptToDispatchEvent( domEventName, eventSystemFlags, targetContainer, nativeEvent, );
attemptToDispatchEvent
先是获取真正的事件触发元素:e.targe,这里称为nativeEventTarget
获取nativeEventTarget上的Fiber,即”__reactFiber${Random…}”属性。这里是targetInst.
处理让targetInst为null的情况。
节点被unmounted,即不能通过return属性到达根节点。
如果最近的mounted是SuspenseCompnent | HostRoot | 最近的mountedFiber !== targetInst
接下来进入真正的事件调度函数。
dispatchEventForPluginEventSystem
在这里面,会有一个mainLoop,去寻找一个root节点,因为在root节点上,会绑定一些事件。
遍历的方式是从当前节点一直往上(return).
最后batchedEventUpdates —> dispatchEventsForPlugins
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function dispatchEventForPluginEventSystem ( domEventName: DOMEventName, eventSystemFlags: EventSystemFlags, nativeEvent: AnyNativeEvent, targetInst: null | Fiber, targetContainer: EventTarget, ): void { let ancestorInst = targetInst; if ( (eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE) === 0 && (eventSystemFlags & IS_NON_DELEGATED) === 0 ) { const targetContainerNode = targetContainer as Node; if (targetInst !== null ) { let node = targetInst; mainLoop: while (true ) { } } } batchedEventUpdates(() => dispatchEventsForPlugins( domEventName, eventSystemFlags, nativeEvent, ancestorInst, targetContainer, ), ); }
dispatchEventsForPlugins
将nativeEvent转换成synthesizeEvent,并加入dispatchQueue,最终processDispatchQueue。
extractEvents:
创建DispatchEntry:{event:listeners},并添加到dispatchQueue
工厂模式确定SyntheticEventCtor
accumulateSinglePhaseListeners从target到root遍历,获取绑定到props的事件处理函数,添加用户自己添加的事件处理函数到listeners数组里并返回。
dispatchQueue.push({event,listeners}) 这里event也就是synthesizeEvent对象,即在事件绑定后的回调函数的默认参数event.
processDispatchQueue:
遍历dispatchQueue,处理每个事件的listeners数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 >}} dispatchQueueexport function processDispatchQueue ( dispatchQueue: DispatchQueue, eventSystemFlags: EventSystemFlags, ): void { const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0 ; for (let i = 0 ; i < dispatchQueue.length; i++) { const { event, listeners } = dispatchQueue[i]; processDispatchQueueItemsInOrder(event, listeners, inCapturePhase); } rethrowCaughtError(); }
processDispatchQueueItemsInOrder
根据inCapturePhase判定是capture还是bubble,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 function processDispatchQueueItemsInOrder ( event: ReactSyntheticEvent, dispatchListeners: Array <DispatchListener>, inCapturePhase: boolean , ): void { let previousInstance; if (inCapturePhase) { for (let i = dispatchListeners.length - 1 ; i >= 0 ; i--) { const { instance, currentTarget, listener } = dispatchListeners[i]; if (instance !== previousInstance && event.isPropagationStopped()) { return ; } executeDispatch(event, listener, currentTarget); previousInstance = instance; } } else { for (let i = 0 ; i < dispatchListeners.length; i++) { const { instance, currentTarget, listener } = dispatchListeners[i]; if (instance !== previousInstance && event.isPropagationStopped()) { return ; } executeDispatch(event, listener, currentTarget); previousInstance = instance; } } }
executeDispatch
最终调用用户的处理函数,其中包含一些react的invoke函数,以及一些在开发环境下的createEvent事件。
本文还有许多细节没有提到,只是大致说明了事件系统的一个流程
未完待续