React中的4種優(yōu)先級(jí)

事件優(yōu)先級(jí):按照用戶事件的交互緊急程度,劃分的優(yōu)先級(jí) 更新優(yōu)先級(jí):事件導(dǎo)致React產(chǎn)生的更新對(duì)象(update)的優(yōu)先級(jí)(update.lane) 任務(wù)優(yōu)先級(jí):產(chǎn)生更新對(duì)象之后,React去執(zhí)行一個(gè)更新任務(wù),這個(gè)任務(wù)所持有的優(yōu)先級(jí) 調(diào)度優(yōu)先級(jí):Scheduler依據(jù)React更新任務(wù)生成一個(gè)調(diào)度任務(wù),這個(gè)調(diào)度任務(wù)所持有的優(yōu)先級(jí)
優(yōu)先級(jí)的起點(diǎn):事件優(yōu)先級(jí)
離散事件(DiscreteEvent):click、keydown、focusin等,這些事件的觸發(fā)不是連續(xù)的,優(yōu)先級(jí)為0。 用戶阻塞事件(UserBlockingEvent):drag、scroll、mouseover等,特點(diǎn)是連續(xù)觸發(fā),阻塞渲染,優(yōu)先級(jí)為1。 連續(xù)事件(ContinuousEvent):canplay、error、audio標(biāo)簽的timeupdate和canplay,優(yōu)先級(jí)最高,為2。
派發(fā)事件優(yōu)先級(jí)
let listener = createEventListenerWrapperWithPriority(targetContainer,domEventName,eventSystemFlags,listenerPriority,);
export function createEventListenerWrapperWithPriority(targetContainer: EventTarget,domEventName: DOMEventName,eventSystemFlags: EventSystemFlags,priority?: EventPriority,): Function {const eventPriority =priority === undefined? getEventPriorityForPluginSystem(domEventName): priority;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,);}
function dispatchUserBlockingUpdate(domEventName,eventSystemFlags,container,nativeEvent,) {...runWithPriority(UserBlockingPriority,dispatchEvent.bind(null,domEventName,eventSystemFlags,container,nativeEvent,),);...}
function unstable_runWithPriority(priorityLevel, eventHandler) {switch (priorityLevel) {case ImmediatePriority:case UserBlockingPriority:case NormalPriority:case LowPriority:case IdlePriority:break;default:priorityLevel = NormalPriority;}var previousPriorityLevel = currentPriorityLevel;// 記錄優(yōu)先級(jí)到Scheduler內(nèi)部的變量里currentPriorityLevel = priorityLevel;try {return eventHandler();} finally {currentPriorityLevel = previousPriorityLevel;}}
更新優(yōu)先級(jí)
const classComponentUpdater = {enqueueSetState(inst, payload, callback) {...// 依據(jù)事件優(yōu)先級(jí)創(chuàng)建update的優(yōu)先級(jí)const lane = requestUpdateLane(fiber, suspenseConfig);const update = createUpdate(eventTime, lane, suspenseConfig);update.payload = payload;enqueueUpdate(fiber, update);// 開始調(diào)度scheduleUpdateOnFiber(fiber, lane, eventTime);...},};
export function requestUpdateLane(fiber: Fiber,suspenseConfig: SuspenseConfig | null,): Lane {...// 根據(jù)記錄下的事件優(yōu)先級(jí),獲取任務(wù)調(diào)度優(yōu)先級(jí)const schedulerPriority = getCurrentPriorityLevel();let lane;if ((executionContext & DiscreteEventContext) !== NoContext &&schedulerPriority === UserBlockingSchedulerPriority) {// 如果事件優(yōu)先級(jí)是用戶阻塞級(jí)別,則直接用InputDiscreteLanePriority去計(jì)算更新優(yōu)先級(jí)lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);} else {// 依據(jù)事件的優(yōu)先級(jí)去計(jì)算schedulerLanePriorityconst schedulerLanePriority = schedulerPriorityToLanePriority(schedulerPriority,);...// 根據(jù)事件優(yōu)先級(jí)計(jì)算得來的schedulerLanePriority,去計(jì)算更新優(yōu)先級(jí)lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);}return lane;}getCurrentPriorityLevel負(fù)責(zé)讀取記錄在Scheduler中的優(yōu)先級(jí):function unstable_getCurrentPriorityLevel() {return currentPriorityLevel;}
任務(wù)優(yōu)先級(jí)
function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {...// 獲取nextLanes,順便計(jì)算任務(wù)優(yōu)先級(jí)const nextLanes = getNextLanes(root,root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,);// 獲取上面計(jì)算得出的任務(wù)優(yōu)先級(jí)const newCallbackPriority = returnNextLanesPriority();...}
它會(huì)被并入root.pendingLanes,root.pendingLanes經(jīng)過getNextLanes處理后,挑出那些應(yīng)該處理的lanes,傳入getHighestPriorityLanes,根據(jù)nextLanes找出這些lanes的優(yōu)先級(jí)作為任務(wù)優(yōu)先級(jí)。
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {...// 都是這種比較賦值的過程,這里只保留兩個(gè)以做簡(jiǎn)要說明const inputDiscreteLanes = InputDiscreteLanes & lanes;if (inputDiscreteLanes !== NoLanes) {return_highestLanePriority = InputDiscreteLanePriority;return inputDiscreteLanes;}if ((lanes & InputContinuousHydrationLane) !== NoLanes) {return_highestLanePriority = InputContinuousHydrationLanePriority;return InputContinuousHydrationLane;}...return lanes;}
export const SyncLanePriority: LanePriority = 17;export const SyncBatchedLanePriority: LanePriority = 16;const InputDiscreteHydrationLanePriority: LanePriority = 15;export const InputDiscreteLanePriority: LanePriority = 14;const InputContinuousHydrationLanePriority: LanePriority = 13;export const InputContinuousLanePriority: LanePriority = 12;const DefaultHydrationLanePriority: LanePriority = 11;export const DefaultLanePriority: LanePriority = 10;const TransitionShortHydrationLanePriority: LanePriority = 9;export const TransitionShortLanePriority: LanePriority = 8;const TransitionLongHydrationLanePriority: LanePriority = 7;export const TransitionLongLanePriority: LanePriority = 6;const RetryLanePriority: LanePriority = 5;const SelectiveHydrationLanePriority: LanePriority = 4;const IdleHydrationLanePriority: LanePriority = 3;const IdleLanePriority: LanePriority = 2;const OffscreenLanePriority: LanePriority = 1;export const NoLanePriority: LanePriority = 0;
調(diào)度優(yōu)先級(jí)
function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {...// 根據(jù)任務(wù)優(yōu)先級(jí)獲取Scheduler的調(diào)度優(yōu)先級(jí)const schedulerPriorityLevel = lanePriorityToSchedulerPriority(newCallbackPriority,);// 計(jì)算出調(diào)度優(yōu)先級(jí)之后,開始讓Scheduler調(diào)度React的更新任務(wù)newCallbackNode = scheduleCallback(schedulerPriorityLevel,performConcurrentWorkOnRoot.bind(null, root),);...}
export function lanePriorityToSchedulerPriority(lanePriority: LanePriority,): ReactPriorityLevel {switch (lanePriority) {case SyncLanePriority:case SyncBatchedLanePriority:return ImmediateSchedulerPriority;case InputDiscreteHydrationLanePriority:case InputDiscreteLanePriority:case InputContinuousHydrationLanePriority:case InputContinuousLanePriority:return UserBlockingSchedulerPriority;case DefaultHydrationLanePriority:case DefaultLanePriority:case TransitionShortHydrationLanePriority:case TransitionShortLanePriority:case TransitionLongHydrationLanePriority:case TransitionLongLanePriority:case SelectiveHydrationLanePriority:case RetryLanePriority:return NormalSchedulerPriority;case IdleHydrationLanePriority:case IdleLanePriority:case OffscreenLanePriority:return IdleSchedulerPriority;case NoLanePriority:return NoSchedulerPriority;default:invariant(false,'Invalid update priority: %s. This is a bug in React.',lanePriority,);}}
總結(jié)

評(píng)論
圖片
表情
