React 源码7:Lane、React和schedule优先级转换
在《源码3》requestUpdateLane函数根据eventLane获取不同情况对应优先级。
一、优先级
1.Lane的tag
一共有32种lane。
var TotalLanes = 31;
var NoLanes =
/* */
0;
var NoLane =
/* */
0;
var SyncLane =
/* */
1;
var InputContinuousHydrationLane =
/* */
2;
var InputContinuousLane =
/* */
4;
var DefaultHydrationLane =
/* */
8;
var DefaultLane =
/* */
16;
var TransitionHydrationLane =
/* */
32;
var TransitionLanes =
/* */
4194240;
var TransitionLane1 =
/* */
64;
var TransitionLane2 =
/* */
128;
var TransitionLane3 =
/* */
256;
var TransitionLane4 =
/* */
512;
var TransitionLane5 =
/* */
1024;
var TransitionLane6 =
/* */
2048;
var TransitionLane7 =
/* */
4096;
var TransitionLane8 =
/* */
8192;
var TransitionLane9 =
/* */
16384;
var TransitionLane10 =
/* */
32768;
var TransitionLane11 =
/* */
65536;
var TransitionLane12 =
/* */
131072;
var TransitionLane13 =
/* */
262144;
var TransitionLane14 =
/* */
524288;
var TransitionLane15 =
/* */
1048576;
var TransitionLane16 =
/* */
2097152;
var RetryLanes =
/* */
130023424;
var RetryLane1 =
/* */
4194304;
var RetryLane2 =
/* */
8388608;
var RetryLane3 =
/* */
16777216;
var RetryLane4 =
/* */
33554432;
var RetryLane5 =
/* */
67108864;
var SomeRetryLane = RetryLane1;
var SelectiveHydrationLane =
/* */
134217728;
var NonIdleLanes =
/* */
268435455;
var IdleHydrationLane =
/* */
268435456;
var IdleLane =
/* */
536870912;
var OffscreenLane =
/* */
1073741824; // This function is used for the experimental timeline (react-devtools-timeline)
// It should be kept in sync with the Lanes values above.
2.React中事件对应的优先级(获取事件对应的优先级getEventPriority函数)
一共有4种优先级。
在getEventPriority中获取事件对应的react优先级,有:
- DiscreteEventPriority(离散事件优先级)
ContinuousEventPriority(连续事件优先级)
DefaultEventPriority(默认优先级)
IdleEventPriority(空间时间优先级)
function getEventPriority(domEventName) {switch (domEventName) {// Used by SimpleEventPlugin:case 'cancel':case 'click':case 'close':case 'contextmenu':case 'copy':case 'cut':case 'auxclick':case 'dblclick':case 'dragend':case 'dragstart':case 'drop':case 'focusin':case 'focusout':case 'input':case 'invalid':case 'keydown':case 'keypress':case 'keyup':case 'mousedown':case 'mouseup':case 'paste':case 'pause':case 'play':case 'pointercancel':case 'pointerdown':case 'pointerup':case 'ratechange':case 'reset':case 'resize':case 'seeked':case 'submit':case 'touchcancel':case 'touchend':case 'touchstart':case 'volumechange': // Used by polyfills:// eslint-disable-next-line no-fallthroughcase 'change':case 'selectionchange':case 'textInput':case 'compositionstart':case 'compositionend':case 'compositionupdate': // Only enableCreateEventHandleAPI:// eslint-disable-next-line no-fallthroughcase 'beforeblur':case 'afterblur': // Not used by React but could be by user code:// eslint-disable-next-line no-fallthroughcase 'beforeinput':case 'blur':case 'fullscreenchange':case 'focus':case 'hashchange':case 'popstate':case 'select':case 'selectstart':return DiscreteEventPriority;case 'drag':case 'dragenter':case 'dragexit':case 'dragleave':case 'dragover':case 'mousemove':case 'mouseout':case 'mouseover':case 'pointermove':case 'pointerout':case 'pointerover':case 'scroll':case 'toggle':case 'touchmove':case 'wheel': // Not used by React but could be by user code:// eslint-disable-next-line no-fallthroughcase 'mouseenter':case 'mouseleave':case 'pointerenter':case 'pointerleave':return ContinuousEventPriority;case 'message':{// We might be in the Scheduler callback.// Eventually this mechanism will be replaced by a check// of the current priority on the native scheduler.//见shceduler优先级转换为React优先级}default:return DefaultEventPriority;}
}
3.schedule中的优先级
一共有5种优先级。
var ImmediatePriority = Scheduler.unstable_ImmediatePriority;
var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;
var NormalPriority = Scheduler.unstable_NormalPriority;
var LowPriority = Scheduler.unstable_LowPriority;
var IdlePriority = Scheduler.unstable_IdlePriority;const unstable_ImmediatePriority = 1;
const unstable_UserBlockingPriority = 2;
const unstable_NormalPriority = 3;
const unstable_IdlePriority = 5;
const unstable_LowPriority = 4;
二、优先级转换的函数
1. lanes优先级转换为React优先级
lane和React全局对应关系:
var DiscreteEventPriority = SyncLane;
var ContinuousEventPriority = InputContinuousLane;
var DefaultEventPriority = DefaultLane;
var IdleEventPriority = IdleLane;
var currentUpdatePriority = NoLane;
lane与React优先级转换:
function lanesToEventPriority(lanes) {var lane = getHighestPriorityLane(lanes);if (!isHigherEventPriority(DiscreteEventPriority, lane)) {return DiscreteEventPriority;}if (!isHigherEventPriority(ContinuousEventPriority, lane)) {return ContinuousEventPriority;}if (includesNonIdleWork(lane)) {return DefaultEventPriority;}return IdleEventPriority;
}
2. React优先级转换为scheduler优先级
var schedulerPriorityLevel;switch (lanesToEventPriority(nextLanes)) {case DiscreteEventPriority:schedulerPriorityLevel = ImmediatePriority;break;case ContinuousEventPriority:schedulerPriorityLevel = UserBlockingPriority;break;case DefaultEventPriority:schedulerPriorityLevel = NormalPriority;break;case IdleEventPriority:schedulerPriorityLevel = IdlePriority;break;default:schedulerPriorityLevel = NormalPriority;break;
}
3.scheduler优先级转换为React优先级
// We might be in the Scheduler callback.
// Eventually this mechanism will be replaced by a check
// of the current priority on the native scheduler.
var schedulerPriority = getCurrentPriorityLevel();switch (schedulerPriority) {case ImmediatePriority:return DiscreteEventPriority;case UserBlockingPriority:return ContinuousEventPriority;case NormalPriority:case LowPriority:// TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration.return DefaultEventPriority;case IdlePriority:return IdleEventPriority;default:return DefaultEventPriority;
}
三、requestUpdateLane函数
暂不考虑transition情况,优先级有四种返回情况:
非并发模式,产生同步优先级
render阶段产生的 update,返回 render 阶段进行中的优先级
使用手动设置的优先级
如果没有手动设置的优先级,则获取当前事件的优先级。
function requestUpdateLane(fiber) {var mode = fiber.mode;if ((mode & ConcurrentMode) === NoMode) {//非并发模式,产生同步优先级return SyncLane;} else if ((executionContext & RenderContext) !== NoContext &&workInProgressRootRenderLanes !== NoLanes) {// render阶段产生的 update,返回 render 阶段进行中的优先级return pickArbitraryLane(workInProgressRootRenderLanes);}//transition情况暂不做讨论//使用手动设置的优先级var updateLane = getCurrentUpdatePriority();if (updateLane !== NoLane) {return updateLane;}//如果没有手动设置的优先级,则获取当前事件的优先级var eventLane = getCurrentEventPriority();return eventLane;
}function getCurrentEventPriority() {var currentEvent = window.event;if (currentEvent === undefined) {return DefaultEventPriority;}//详见本文(一、优先级)第二节getEventPriority函数,返回React优先级return getEventPriority(currentEvent.type);
}//currentUpdatePriority是存储优先级的全局变量
function getCurrentUpdatePriority() {return currentUpdatePriority;
}