反応ソースコードのライフサイクルとイベントシステム

この章であなたと議論したいのは、イエスReactとノーです。生命周期事件系统

jsxのコンパイル結果

jsx上記でv17コンパイル結果にも言及したので标签名、他のタグ属性( などclass) や事件(clickイベントなど) を除いて、それらはすべて_jsxRuntime.jsx関数の第 2 パラメーターに配置されます。パフォーマンスの形でkey:value、ここではいくつかの問題があります。

  • react関数本体 (イベント ハンドラー) が何であるかをどのように知ることができますか?
  • reactこれらのイベントはどの段階で処理されますか?

最初にここでポイントを作りましょう. まず最初にReact完全なアプリケーションの完全なライフサイクルがどのように見えるかを見てみましょう. 私たちは皆、それが2つのコンポーネントのライフサイクル機能にReact分割され类组件、その一部であることを知っています.ここで私は分析します. 2 つのコンポーネントを別々にコンポーネントのライフ サイクルを説明します。函数组件发生了一些变化

React コンポーネントのライフサイクル

コンポーネント実装時の実行順序

_jsxRuntime.jsxオブジェクトをコンパイルするときに、処理静的型チェックjsxを行うためです。したがって、これもライフサイクルです。コンポーネントは分離されており、このコンストラクタは段階的に実行されます.私はいくつかの調査を行いました.これはクラスコンポーネントに固有のものですか、それとも固有のものですか? 後で、これ独特であることがわかりました。この文をどのように理解するのですか?defaultPropspropTypeClassconstructormountconstructorclassconstructorclass

  • 「Re-learning ES6」という本で言及されています:ES6クラスの概念が に追加されました。クラスにはメソッドが必要です。constructorクラスに明示的な定義がない場合、デフォルトで空のconstructorメソッドが追加されます。ReactClassComponent話すためconstructorに必要な関数は、stateイベントを初期化してバインドすることです. もう1つのポイントは、宣言さconstructorれた後に呼び出される必要があることですsuper. 私たちは通常、それを受け取りとprops受け渡しに使用します. 書かないconstructor動かない.propsconstructorpropssuper
  • したがって、クラス コンポーネントの場合constructorは、ライフ サイクル フックと見なすことができます。

getDerivedStateFromPropsrender メソッドが呼び出される前に呼び出され、最初のマウントとその後の更新で呼び出されます。オブジェクトを更新状態に戻す必要があります。何もnull返さ更新されません。

render呼び出されるthis.propsthis.state、次のいずれかのタイプを返します。

  • 反応要素通常、JSX 経由で作成されます。たとえば、 React によって<div />DOM ノードとしてレンダリングされ、React 要素<MyComponent />である<div /><MyComponent />
  • 配列またはフラグメントrender メソッドが複数の要素を返すことができるようにします。
  • ポータル子ノードを異なる DOM サブツリーにレンダリングすることができます。
  • 文字列または数値型これらは、DOM でテキスト ノードとしてレンダリングされます。
  • ブール値またはnull. 何もレンダリングされません。(主に、 test がブール値である をtest && <Child />返すます。)

componentDidMount()コンポーネントがマウントされた (DOM ツリーに挿入された) 直後に呼び出されます。DOM ノードに依存する初期化はここで行う必要があります。これは、非同期リクエストの送信に適しています。

コンポーネント更新時の実行順序

getDerivedStateFromProps=> shouldComponentUpdate()=> render()=> getSnapshotBeforeUpdate()=>componentDidUpdate()

  • これshouldComponentUpdateは、パフォーマンス最適化のフックとも呼ばれます. その機能は、2 つの更新を比較するか、stateまたはpropsそれらが変更されたかどうかを比較し、現在のコンポーネントを更新するかどうかを決定することです. 比較方法については浅比较、以前に説明したので、ここでは繰り返しません.
  • そして、getSnapshotBeforeUpdate関数は、最新のレンダリングされた出力 (DOMノードに送信される) の前に呼び出されます。これにより、コンポーネントは、変更前にコンポーネントDOMから。このライフサイクル メソッドからの戻り値は、引数として に渡されますcomponentDidUpdate()
  • componentDidUpdate()更新直後に呼び出されます。不会执行このメソッドは最初にレンダリングされます。

コンポーネントのアンインストール時の実行順序

componentWillUnmount()componentの直前卸载に呼び出されます销毁cleanup など、このメソッドで必要なクリーンアップ操作を実行しますtimer取消网络请求

エラー発生時のコンポーネントの実行順序

getDerivedStateFromErrorcomponentDidCatchこの2つのフックについては、学生が自分で公式サイトに移動できます。

もちろん、上記はClassComponentライフサイクルの実行順序に過ぎず、新しいバージョンの ReactcomponentDidMountではcomponentDidUpdate、 、 、 が削除されcomponentWillUnMountに置き換えられています。では、正確に3人を置き換えたのは誰ですか? この問題については、React のソース コード分析シリーズ (8) - 詳細なフックの原則で説明したので、ここでは繰り返しません。useEffectuseLayoutEffect

ここで、最初の質問に答えます。reactは関数の本体が何であるかをどのように認識しますか? この質問は実際には非常に良い質問です.babel解析後はそれにjsx注意を払うだけですが{事件名:函数名}、各イベントを登録してバインドし、イベントによってトリガーされて、バインドされた関数の関数本体を実行する必要があります. この種の問題を説明するには、ソース コード内の特定の実装を確認する必要があります。

listenToAllSupportedEvents

Reactソースコード解析連載(2)で紹介した初期化コンポーネントの作成・更新処理.rootFiber作成FiberRootが完了したらイベントを作成する必要があります.イベントを作成するためのエントリ関数はlistenToAllSupportedEvents.

// packages/react-dom/src/events/DOMPluginEventSystem.js
export function listenToAllSupportedEvents(rootContainerElement: EventTarget) {if (enableEagerRootListeners) { // enableEagerRootListeners默认值为false// listeningMarker就是一个随机数+字符串,作为唯一值if (rootContainerElement[listeningMarker]) {...return;}rootContainerElement[listeningMarker] = true;// 遍历allNativeEvents的所有事件allNativeEvents.forEach(domEventName => {// 如果不是委托事件,没有冒泡阶段// nonDelegatedEvents全部媒体事件,if (!nonDelegatedEvents.has(domEventName)) {listenToNativeEvent(domEventName,false,((rootContainerElement: any): Element),null,);}// 有冒泡阶段listenToNativeEvent(domEventName,true,((rootContainerElement: any): Element),null,);});}
}

//listeningMarker
// 唯一标识
const listeningMarker ='_reactListening' +Math.random().toString(36).slice(2); 

allNativeEventsここにあるものに注意を払う必要があります。これは、イベント名を格納allNativeEventsする構造体としてソース コードに反映されています。Set

export const allNativeEvents: Set<DOMEventName> = new Set(); 

listenToNativeEvent次に何が起こったのか見てみましょう。

listenToNativeEvent

export function listenToNativeEvent( domEventName: DOMEventName,// 事件名isCapturePhaseListener: boolean, // 根据上个函数,这里应该是确定是是能够冒泡的事件rootContainerElement: EventTarget,targetElement: Element | null,eventSystemFlags?: EventSystemFlags = 0, // 事件标记 ): void {let target = rootContainerElement;//如果是selectionchange事件,加到dom上if (domEventName === 'selectionchange' &&(rootContainerElement: any).nodeType !== DOCUMENT_NODE) {target = (rootContainerElement: any).ownerDocument;}if (targetElement !== null &&!isCapturePhaseListener &&nonDelegatedEvents.has(domEventName) // 非冒泡事件) { ...//滚动事件不冒泡if (domEventName !== 'scroll') {return;}eventSystemFlags |= IS_NON_DELEGATED; // is_non_delegated 不是委托事件target = targetElement;}//获取dom上绑定的事件名数组 Set[] || const listenerSet = getEventListenerSet(target);// 处理事件名为捕获阶段与冒泡阶段 Set[click_bubble]const listenerSetKey = getListenerSetKey(domEventName,isCapturePhaseListener,);// 把没有打过的IS_CAPTURE_PHASE的符合条件的事件,打上标签if (!listenerSet.has(listenerSetKey)) {if (isCapturePhaseListener) {// 打上捕获的标签eventSystemFlags |= IS_CAPTURE_PHASE;}// 往节点上添加事件绑定addTrappedEventListener(target,domEventName,eventSystemFlags,isCapturePhaseListener,);// 往listenerSet中添加事件名listenerSet.add(listenerSetKey);}
}

//getEventListenerSet
export function getEventListenerSet(node: EventTarget): Set<string> {let elementListenerSet = (node: any)[internalEventHandlersKey];if (elementListenerSet === undefined) {// 创建一个Set来存放事件名elementListenerSet = (node: any)[internalEventHandlersKey] = new Set();}return elementListenerSet;
}

// getListenerSetKey
export function getListenerSetKey( domEventName: DOMEventName,capture: boolean, ): string {// capture捕获,bubble冒泡return `${domEventName}__${capture ? 'capture' : 'bubble'}`;
}

// addTrappedEventListener
function addTrappedEventListener( targetContainer: EventTarget, // 容器domEventName: DOMEventName, // 事件名eventSystemFlags: EventSystemFlags, //事件名标识isCapturePhaseListener: boolean, // 事件委托isDeferredListenerForLegacyFBSupport?: boolean, ) {// 创建具有优先级的事件监听函数,返回值为functionlet listener = createEventListenerWrapperWithPriority(targetContainer,domEventName,eventSystemFlags,);...targetContainer =enableLegacyFBSupport && isDeferredListenerForLegacyFBSupport? (targetContainer: any).ownerDocument: targetContainer;let unsubscribeListener;...// 区分捕获、冒泡 通过node.addEventListener绑定事件到节点上if (isCapturePhaseListener) {if (isPassiveListener !== undefined) {unsubscribeListener = addEventCaptureListenerWithPassiveFlag(targetContainer,domEventName,listener,isPassiveListener,);} else {unsubscribeListener = addEventCaptureListener(targetContainer,domEventName,listener,);}} else {if (isPassiveListener !== undefined) {unsubscribeListener = addEventBubbleListenerWithPassiveFlag(targetContainer,domEventName,listener,isPassiveListener,);} else {unsubscribeListener = addEventBubbleListener(targetContainer,domEventName,listener,);}}
}

// createEventListenerWrapperWithPriority
export function createEventListenerWrapperWithPriority( targetContainer: EventTarget, // 容器domEventName: DOMEventName, // 事件名eventSystemFlags: EventSystemFlags, //标识 ): Function {// 获取事件Map里面已经标记好的优先级const eventPriority = getEventPriorityForPluginSystem(domEventName);let listenerWrapper;// 根据优先级不同绑定不同的执行函数switch (eventPriority) {//离散事件case DiscreteEvent:listenerWrapper = dispatchDiscreteEvent;break;// 用户交互阻塞渲染的事件 case UserBlockingEvent:listenerWrapper = dispatchUserBlockingUpdate;break;// 其他事件case ContinuousEvent:// 默认事件default:listenerWrapper = dispatchEvent;break;}return listenerWrapper.bind(null,domEventName,eventSystemFlags,targetContainer,);
} 

getEventPriorityForPluginSystem質問がありますか? 内部イベントは確実に優先されることはわかっていますが、イベントReact以外のイベントについてはどうでしょうか。心配しないでください。見ればわかります。ReactReact原生事件

getEventPriorityForPluginSystem

export function getEventPriorityForPluginSystem( domEventName: DOMEventName, ): EventPriority {// 通过事件名获取优先级const priority = eventPriorities.get(domEventName);// ContinuousEvent为默认优先级 return priority === undefined ? ContinuousEvent : priority;
}

//eventPriorities
const eventPriorities = new Map(); 

eventPrioritiesそれ自体が Map 構造であり、2 つの場所で実行される操作を見つけることができますeventPriorities.set()

// packages/react-dom/src/events/DOMEventProperties.js
function setEventPriorities( eventTypes: Array<DOMEventName>,priority: EventPriority, ): void {for (let i = 0; i < eventTypes.length; i++) {// 往eventPriorities添加优先级eventPriorities.set(eventTypes[i], priority);}
}

//registerSimplePluginEventsAndSetTheirPriorities
function registerSimplePluginEventsAndSetTheirPriorities( eventTypes: Array<DOMEventName | string>,priority: EventPriority, ): void {for (let i = 0; i < eventTypes.length; i += 2) {const topEvent = ((eventTypes[i]: any): DOMEventName);const event = ((eventTypes[i + 1]: any): string);const capitalizedEvent = event[0].toUpperCase() + event.slice(1);// 改变事件名 click => onClickconst reactName = 'on' + capitalizedEvent;// 往eventPriorities添加优先级eventPriorities.set(topEvent, priority);topLevelEventsToReactNames.set(topEvent, reactName);// 注册捕获阶段,冒泡阶段的事件registerTwoPhaseEvent(reactName, [topEvent]);}
} 

これは、この 2 つの関数で優先処理が行われていることを意味するので、この 2 つの関数がどこで呼び出されているかを見ると、関数registerSimpleEventsでこれら 2 つの関数がeventPriorities実行され、優先順位が付けられていることがわかりました。

// packages/react-dom/src/events/DOMEventProperties.js
export function registerSimpleEvents() {// 处理离散事件优先级registerSimplePluginEventsAndSetTheirPriorities(discreteEventPairsForSimpleEventPlugin,DiscreteEvent,);// 处理用户阻塞事件优先级registerSimplePluginEventsAndSetTheirPriorities(userBlockingPairsForSimpleEventPlugin,UserBlockingEvent,);// 处理默认事件优先级registerSimplePluginEventsAndSetTheirPriorities(continuousPairsForSimpleEventPlugin,ContinuousEvent,);// 处理其他事件优先级setEventPriorities(otherDiscreteEvents, DiscreteEvent);
} 

上記のコードには多くのコードがあることがわかりますPlugin。コードは次のとおりです。

const discreteEventPairsForSimpleEventPlugin = [('cancel': DOMEventName), 'cancel',('click': DOMEventName), 'click',('close': DOMEventName), 'close',('contextmenu': DOMEventName), 'contextMenu',('copy': DOMEventName), 'copy',('cut': DOMEventName), 'cut',('auxclick': DOMEventName), 'auxClick',('dblclick': DOMEventName), 'doubleClick', // Careful!('dragend': DOMEventName), 'dragEnd',('dragstart': DOMEventName), 'dragStart',('drop': DOMEventName), 'drop',('focusin': DOMEventName), 'focus', // Careful!('focusout': DOMEventName), 'blur', // Careful!('input': DOMEventName), 'input',('invalid': DOMEventName), 'invalid',('keydown': DOMEventName), 'keyDown',('keypress': DOMEventName), 'keyPress',('keyup': DOMEventName), 'keyUp',('mousedown': DOMEventName), 'mouseDown',('mouseup': DOMEventName), 'mouseUp',('paste': DOMEventName), 'paste',('pause': DOMEventName), 'pause',('play': DOMEventName), 'play',('pointercancel': DOMEventName), 'pointerCancel',('pointerdown': DOMEventName), 'pointerDown',('pointerup': DOMEventName), 'pointerUp',('ratechange': DOMEventName), 'rateChange',('reset': DOMEventName), 'reset',('seeked': DOMEventName), 'seeked',('submit': DOMEventName), 'submit',('touchcancel': DOMEventName), 'touchCancel',('touchend': DOMEventName), 'touchEnd',('touchstart': DOMEventName), 'touchStart',('volumechange': DOMEventName), 'volumeChange',
];

const otherDiscreteEvents: Array<DOMEventName> = ['change','selectionchange','textInput','compositionstart','compositionend','compositionupdate',
];

const userBlockingPairsForSimpleEventPlugin: Array<string | DOMEventName> = [('drag': DOMEventName), 'drag',('dragenter': DOMEventName), 'dragEnter',('dragexit': DOMEventName), 'dragExit',('dragleave': DOMEventName), 'dragLeave',('dragover': DOMEventName), 'dragOver',('mousemove': DOMEventName), 'mouseMove',('mouseout': DOMEventName), 'mouseOut',('mouseover': DOMEventName), 'mouseOver',('pointermove': DOMEventName), 'pointerMove',('pointerout': DOMEventName), 'pointerOut',('pointerover': DOMEventName), 'pointerOver',('scroll': DOMEventName), 'scroll',('toggle': DOMEventName), 'toggle',('touchmove': DOMEventName), 'touchMove',('wheel': DOMEventName), 'wheel',
];

const continuousPairsForSimpleEventPlugin: Array<string | DOMEventName> = [('abort': DOMEventName), 'abort',(ANIMATION_END: DOMEventName), 'animationEnd',(ANIMATION_ITERATION: DOMEventName), 'animationIteration',(ANIMATION_START: DOMEventName), 'animationStart',('canplay': DOMEventName), 'canPlay',('canplaythrough': DOMEventName), 'canPlayThrough',('durationchange': DOMEventName), 'durationChange',('emptied': DOMEventName), 'emptied',('encrypted': DOMEventName), 'encrypted',('ended': DOMEventName), 'ended',('error': DOMEventName), 'error',('gotpointercapture': DOMEventName), 'gotPointerCapture',('load': DOMEventName), 'load',('loadeddata': DOMEventName), 'loadedData',('loadedmetadata': DOMEventName), 'loadedMetadata',('loadstart': DOMEventName), 'loadStart',('lostpointercapture': DOMEventName), 'lostPointerCapture',('playing': DOMEventName), 'playing',('progress': DOMEventName), 'progress',('seeking': DOMEventName), 'seeking',('stalled': DOMEventName), 'stalled',('suspend': DOMEventName), 'suspend',('timeupdate': DOMEventName), 'timeUpdate',(TRANSITION_END: DOMEventName), 'transitionEnd',('waiting': DOMEventName), 'waiting',
]; 

registerSimplePluginEventsAndSetTheirPriorities関数で、登録イベントを見つけましたregisterTwoPhaseEvent登録方法を調べてみましょう。

registerTwoPhaseEvent

export function registerTwoPhaseEvent( registrationName: string, // 注册事件reactNamedependencies: Array<DOMEventName>, // 依赖 ): void {registerDirectEvent(registrationName, dependencies);registerDirectEvent(registrationName + 'Capture', dependencies);
} 

registerDirectEvent

// Mapping from registration name to event name
export const registrationNameDependencies = {};

export function registerDirectEvent( registrationName: string, //react事件名onClickdependencies: Array<DOMEventName>, // 依赖 ) {...// 以react事件名为key,dependencies为value的map对象registrationNameDependencies[registrationName] = dependencies;if (__DEV__) {...}// 遍历依赖,把每一项加入到allNativeEvents中去for (let i = 0; i < dependencies.length; i++) {allNativeEvents.add(dependencies[i]);}
} 

allNativeEvents保存イベント名とのことで、Setここに追加して事件名完了事件注册です。まだ終わっていません.イベント登録はイベントにバインドされていると前述しましたが、ユーザーがクリックしたとき、どのようにトリガーする必要がありますか? 上記のコードでは、優先度を取得した後、各イベントは現在の優先度に従って 1 つを生成します。listenerWrapperこれlistenerWrapperは、対応するイベント トリガー バインディング関数です。dispatchDiscreteEventdispatchUserBlockingUpdate、およびdispatchEvent3 つの関数はすべてバインドによって実行されますが、バインドによってバインドされた関数が新しい関数を返し、すぐには実行されないことは誰もが知っています。したがって、彼のエントリが何であるかも確認する必要があります。

  • this:null
  • argments: domEventName: イベント名、eventSystemFlags: イベント タイプ タグ、targetContainer: 対象のコンテナ。

ディスパッチイベント

それが何であれdispatchDiscreteEvent、最後にdispatchUserBlockingUpdate実行されるdispatchEventので、彼の実装を見ることができます。

// packages/react-dom/src/events/ReactDOMEventListener.js
export function dispatchEvent( domEventName: DOMEventName, // 事件名eventSystemFlags: EventSystemFlags, // 事件类型标记targetContainer: EventTarget, // 目标容器nativeEvent: AnyNativeEvent, // native事件 ): void {...// 如果被阻塞了,尝试调度事件 并返回挂载的实例或者容器const blockedOn = attemptToDispatchEvent(domEventName,eventSystemFlags,targetContainer,nativeEvent,);if (blockedOn === null) {// We successfully dispatched this event....return;}...// 调度事件,触发事件dispatchEventForPluginEventSystem(domEventName,eventSystemFlags,nativeEvent,null,targetContainer,);
}

// dispatchEventForPluginEventSystem
export function dispatchEventForPluginEventSystem( domEventName: DOMEventName,eventSystemFlags: EventSystemFlags,nativeEvent: AnyNativeEvent,targetInst: null | Fiber,targetContainer: EventTarget, ): void {...//批量更新事件 batchedEventUpdates(() =>dispatchEventsForPlugins(domEventName,eventSystemFlags,nativeEvent,ancestorInst,targetContainer,),);
}

// batchedEventUpdates
export function batchedEventUpdates(fn, a, b) {...isBatchingEventUpdates = true;try {// fn : ()=>dispatchEventsForPlugins//(domEventName,eventSystemFlags,ativeEvent,ancestorInst,targetContainer,),// a: undefined// b: undefinedreturn batchedEventUpdatesImpl(fn, a, b); // batchedEventUpdatesImpl(fn, a, b) =>// Defaults// let batchedUpdatesImpl = function(fn, bookkeeping) {// return fn(bookkeeping); 执行dispatchEventsForPlugins
};} finally {...}
} 

dispatchEventsForPlugins

function dispatchEventsForPlugins( domEventName: DOMEventName,eventSystemFlags: EventSystemFlags,nativeEvent: AnyNativeEvent,targetInst: null | Fiber,targetContainer: EventTarget, ): void {const nativeEventTarget = getEventTarget(nativeEvent);const dispatchQueue: DispatchQueue = [];//创建合成事件,遍历fiber链表,将会触发的事件加入到dispatchQueue中extractEvents(dispatchQueue,domEventName,targetInst,nativeEvent,nativeEventTarget,eventSystemFlags,targetContainer,);//触发时间队列,执行事件processDispatchQueue(dispatchQueue, eventSystemFlags);
}

//extractEvents
function extractEvents( dispatchQueue: DispatchQueue,domEventName: DOMEventName,targetInst: null | Fiber,nativeEvent: AnyNativeEvent,nativeEventTarget: null | EventTarget,eventSystemFlags: EventSystemFlags,targetContainer: EventTarget, ) {...let from;let to;...const leave = new SyntheticEventCtor(leaveEventType,eventTypePrefix + 'leave',from,nativeEvent,nativeEventTarget,);leave.target = fromNode;leave.relatedTarget = toNode;let enter: KnownReactSyntheticEvent | null = null;...accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leave, enter, from, to);
}

//accumulateEnterLeaveTwoPhaseListeners
export function accumulateEnterLeaveTwoPhaseListeners( dispatchQueue: DispatchQueue,leaveEvent: KnownReactSyntheticEvent,enterEvent: null | KnownReactSyntheticEvent,from: Fiber | null,to: Fiber | null, ): void {const common = from && to ? getLowestCommonAncestor(from, to) : null;if (from !== null) {accumulateEnterLeaveListenersForEvent(dispatchQueue,leaveEvent,from,common,false,);}if (to !== null && enterEvent !== null) {accumulateEnterLeaveListenersForEvent(dispatchQueue,enterEvent,to,common,true,);}
}

// accumulateEnterLeaveListenersForEvent
function accumulateEnterLeaveListenersForEvent( dispatchQueue: DispatchQueue,event: KnownReactSyntheticEvent,target: Fiber,common: Fiber | null,inCapturePhase: boolean, ): void {// 获取注册的事件名const registrationName = event._reactName;// 事件处理函数容器const listeners: Array<DispatchListener> = [];//节点实例let instance = target;// 遍历fiber,获取fiber上的事件对应的事件处理函数while (instance !== null) {if (instance === common) {break;}const {alternate, stateNode, tag} = instance;if (alternate !== null && alternate === common) {break;}if (tag === HostComponent && stateNode !== null) {const currentTarget = stateNode;// 根据捕获阶段,还是冒泡阶段处理不同的函数逻辑if (inCapturePhase) {const captureListener = getListener(instance, registrationName);if (captureListener != null) {// 加入到listeners中// instance:当前fiebr实例// currentTarget:当前domlisteners.unshift(createDispatchListener(instance, captureListener, currentTarget),);}} else if (!inCapturePhase) {// 冒泡const bubbleListener = getListener(instance, registrationName);if (bubbleListener != null) {// 加入到listeners中listeners.push(createDispatchListener(instance, bubbleListener, currentTarget),);}}}// 当前fiber实例的父级instance = instance.return;}if (listeners.length !== 0) {// 把事件、事件处理函数全部推到dispatchQueue中dispatchQueue.push({event, listeners});}
}
// processDispatchQueue
export 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);//event system doesn't use pooling.}// This would be a good time to rethrow if any of the event handlers threw.rethrowCaughtError();
} 

React以上でイベントシステムの解析は終わり、上記の疑問はここで簡単に解けます.イベントReact名とイベント処理関数のペアが束縛创建rootFiber事件注册. 次に、それらの実行プロセスはおおよそ次のとおりです。事件绑定事件调度

要約する

この章では、主にmount、 、update、およびフェーズdestroyのコンポーネントのライフサイクル実行シーケンスとReact、イベント システムの登録、バインディング、スケジュール更新などについて紹介します。

やっと

HTML、CSS、JavaScript、HTTP、TCPプロトコル、ブラウザ、VUE、React、データ構造やアルゴリズムなど、「フロントエンドメーカーインタビュー集」をまとめ、合計201問のインタビュー質問をまとめ、それぞれに回答を作成質問 答えて分析します。

困っている友達、記事の最後にあるカードをクリックしてこのドキュメントを受け取り、無料で共有できます

ドキュメントの一部は次のとおりです。



記事の長さには制限があり、次のコンテンツは順次表示されません

困っている友達は、下のカードをクリックして無料で入手できます

おすすめ

転載: blog.csdn.net/web22050702/article/details/128653976