React中的4种优先级

事件优先级:按照用户事件的交互紧急程度,划分的优先级 更新优先级:事件导致React产生的更新对象(update)的优先级(update.lane) 任务优先级:产生更新对象之后,React去执行一个更新任务,这个任务所持有的优先级 调度优先级:Scheduler依据React更新任务生成一个调度任务,这个调度任务所持有的优先级
优先级的起点:事件优先级
离散事件(DiscreteEvent):click、keydown、focusin等,这些事件的触发不是连续的,优先级为0。 用户阻塞事件(UserBlockingEvent):drag、scroll、mouseover等,特点是连续触发,阻塞渲染,优先级为1。 连续事件(ContinuousEvent):canplay、error、audio标签的timeupdate和canplay,优先级最高,为2。
派发事件优先级
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;// 记录优先级到Scheduler内部的变量里currentPriorityLevel = priorityLevel;try {return eventHandler();} finally {currentPriorityLevel = previousPriorityLevel;}}
更新优先级
const classComponentUpdater = {enqueueSetState(inst, payload, callback) {...// 依据事件优先级创建update的优先级const lane = requestUpdateLane(fiber, suspenseConfig);const update = createUpdate(eventTime, lane, suspenseConfig);update.payload = payload;enqueueUpdate(fiber, update);// 开始调度scheduleUpdateOnFiber(fiber, lane, eventTime);...},};
export function requestUpdateLane(fiber: Fiber,suspenseConfig: SuspenseConfig | null,): Lane {...// 根据记录下的事件优先级,获取任务调度优先级const schedulerPriority = getCurrentPriorityLevel();let lane;if ((executionContext & DiscreteEventContext) !== NoContext &&schedulerPriority === UserBlockingSchedulerPriority) {// 如果事件优先级是用户阻塞级别,则直接用InputDiscreteLanePriority去计算更新优先级lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);} else {// 依据事件的优先级去计算schedulerLanePriorityconst schedulerLanePriority = schedulerPriorityToLanePriority(schedulerPriority,);...// 根据事件优先级计算得来的schedulerLanePriority,去计算更新优先级lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);}return lane;}getCurrentPriorityLevel负责读取记录在Scheduler中的优先级:function unstable_getCurrentPriorityLevel() {return currentPriorityLevel;}
任务优先级
function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {...// 获取nextLanes,顺便计算任务优先级const nextLanes = getNextLanes(root,root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,);// 获取上面计算得出的任务优先级const newCallbackPriority = returnNextLanesPriority();...}
它会被并入root.pendingLanes,root.pendingLanes经过getNextLanes处理后,挑出那些应该处理的lanes,传入getHighestPriorityLanes,根据nextLanes找出这些lanes的优先级作为任务优先级。
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {...// 都是这种比较赋值的过程,这里只保留两个以做简要说明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;
调度优先级
function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {...// 根据任务优先级获取Scheduler的调度优先级const schedulerPriorityLevel = lanePriorityToSchedulerPriority(newCallbackPriority,);// 计算出调度优先级之后,开始让Scheduler调度React的更新任务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,);}}
总结

评论
