前言
上节我们在讲updateContainer的时候,我们通过requestUpdateLane(current)创建一个lane,然后将这个lane传入了updateContainerImpl方法中,而updateContainerImpl中又将lane传入了createUpdate方法来创建一个新的更新,所以lane是什么呢?
其实它就是react中的优先级模型,react会对应不同的任务给予不同的优先级,这样react就知道哪些任务更加重要,需要优先做,哪些没那么重要,可以慢点做,而高优先级的任务是可以打断低优先级的任务的
而它的本质就是一个31位的二进制,所以react中就可以有31种优先级
比如说: 0b0000000000000000000000000000000就代表NoLane,也就是没有优先级, 0b0000000000000000000000000000010代表SyncLane,也就是同步优先级。
为什么用二进制
因为二进制能直接使用位运算,性能好,可以用一个值很好的表示lane的集合lanes
比如:0b0000000000000000000000000000011就代表了0b0000000000000000000000000000010和
0b0000000000000000000000000000001的叠加态
那么0b0000000000000000000000000000011就是一个lanes
有哪些lane和lanes
lane的主要逻辑在:packages/react-reconciler/src/ReactFiberLane.js
这里我贴出react中所有的lane和lanes声明
// 总lane的数量
export const TotalLanes = 31;
// 没有lanes
export const NoLanes: Lanes = 0b0000000000000000000000000000000;
// 没有lane
export const NoLane: Lane = 0b0000000000000000000000000000000;
// 同步水合lane
export const SyncHydrationLane: Lane = 0b0000000000000000000000000000001;
// 同步lane
export const SyncLane: Lane = 0b0000000000000000000000000000010;
// 持续输入水合lane
export const InputContinuousHydrationLane: Lane = 0b0000000000000000000000000000100;
// 持续输入lane
export const InputContinuousLane: Lane = 0b0000000000000000000000000001000;
// 默认水合lane
export const DefaultHydrationLane: Lane = 0b0000000000000000000000000010000;
// 默认lane
export const DefaultLane: Lane = 0b0000000000000000000000000100000;
// 同步更新lanes
export const SyncUpdateLanes: Lane = enableUnifiedSyncLane
? SyncLane | InputContinuousLane | DefaultLane
: SyncLane;
const TransitionHydrationLane: Lane =
0b0000000000000000000000001000000;
const TransitionLanes: Lanes = 0b0000000001111111111111110000000;
const TransitionLane1: Lane = 0b0000000000000000000000010000000;
const TransitionLane2: Lane = 0b0000000000000000000000100000000;
const TransitionLane3: Lane = 0b0000000000000000000001000000000;
const TransitionLane4: Lane = 0b0000000000000000000010000000000;
const TransitionLane5: Lane = 0b0000000000000000000100000000000;
const TransitionLane6: Lane = 0b0000000000000000001000000000000;
const TransitionLane7: Lane = 0b0000000000000000010000000000000;
const TransitionLane8: Lane = 0b0000000000000000100000000000000;
const TransitionLane9: Lane = 0b0000000000000001000000000000000;
const TransitionLane10: Lane = 0b0000000000000010000000000000000;
const TransitionLane11: Lane = 0b0000000000000100000000000000000;
const TransitionLane12: Lane = 0b0000000000001000000000000000000;
const TransitionLane13: Lane = 0b0000000000010000000000000000000;
const TransitionLane14: Lane = 0b0000000000100000000000000000000;
const TransitionLane15: Lane = 0b0000000001000000000000000000000;
const RetryLanes: Lanes= 0b0000011110000000000000000000000;
const RetryLane1: Lane = 0b0000000010000000000000000000000;
const RetryLane2: Lane = 0b0000000100000000000000000000000;
const RetryLane3: Lane = 0b0000001000000000000000000000000;
const RetryLane4: Lane = 0b0000010000000000000000000000000;
export const SomeRetryLane: Lane = RetryLane1;
export const SelectiveHydrationLane: Lane =
0b0000100000000000000000000000000;
const NonIdleLanes: Lanes = 0b0000111111111111111111111111111;
export const IdleHydrationLane: Lane = 0b0001000000000000000000000000000;
// 空闲时lane
export const IdleLane: Lane = 0b0010000000000000000000000000000;
export const OffscreenLane: Lane = 0b0100000000000000000000000000000;
export const DeferredLane: Lane = 0b1000000000000000000000000000000;
// 更新lanes
export const UpdateLanes: Lanes =
SyncLane | InputContinuousLane | DefaultLane | TransitionLanes;
btw:Hydration(水合)是什么?
在 React 中,Hydration是指在服务器端渲染(SSR)的 React 应用中,将服务器生成的 HTML 与客户端上的 React 组件关联起来的过程。这一过程通常发生在浏览器加载了服务端渲染的 HTML 和客户端 JavaScript 代码之后。Hydration 确保了客户端应用能够接管服务器端渲染出的静态内容,并添加事件处理器以及其他需要浏览器 API 实现的交互性能力。
获取最高优先级的lane和lanes
既然lane是优先级模型,我们肯定需要能够获取最高优先级的lane和lanes,在lane模型中,数值越小优先级越高
获取最高优先级的lane
可以看到方法很简单,这就是位运算的优势了,其实这里取最高优先级的lane就是取lanes的最右位的值
export function getHighestPriorityLane(lanes: Lanes): Lane {
return lanes & -lanes;
}
比如:
const lanes = 0b0000000000000000000000000011110
const notLanes = -lanes
const highestPriorityLane = lanes & notLanes
// 2 (0b0000000000000000000000000000010)
最高优先级的lane就是0b0000000000000000000000000000010,对应的同步lane
获取最高优先级的lanes
和getHighestPriorityLane差不多,下一个
/** enableUnifiedSyncLane默认为true,所以SyncUpdateLanes默认为第一种结果,也就是
* 0b0000000000000000000000000101010
*/
export const SyncUpdateLanes: Lane = enableUnifiedSyncLane
? SyncLane | InputContinuousLane | DefaultLane
: SyncLane;
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
// enableUnifiedSyncLane默认为true,来自shared/ReactFeatureFlags
if (enableUnifiedSyncLane) {
const pendingSyncLanes = lanes & SyncUpdateLanes;
// 如果当前lane有同步的情况,直接return
if (pendingSyncLanes !== 0) {
return pendingSyncLanes;
}
}
// 从lanes中选出优先级最高的lane然后return
switch (getHighestPriorityLane(lanes)) {
case SyncHydrationLane:
return SyncHydrationLane;
case SyncLane:
return SyncLane;
case InputContinuousHydrationLane:
return InputContinuousHydrationLane;
case InputContinuousLane:
return InputContinuousLane;
case DefaultHydrationLane:
return DefaultHydrationLane;
case DefaultLane:
return DefaultLane;
case TransitionHydrationLane:
return TransitionHydrationLane;
case TransitionLane1:
case TransitionLane2:
case TransitionLane3:
case TransitionLane4:
case TransitionLane5:
case TransitionLane6:
case TransitionLane7:
case TransitionLane8:
case TransitionLane9:
case TransitionLane10:
case TransitionLane11:
case TransitionLane12:
case TransitionLane13:
case TransitionLane14:
case TransitionLane15:
return lanes & TransitionLanes;
case RetryLane1:
case RetryLane2:
case RetryLane3:
case RetryLane4:
return lanes & RetryLanes;
case SelectiveHydrationLane:
return SelectiveHydrationLane;
case IdleHydrationLane:
return IdleHydrationLane;
case IdleLane:
return IdleLane;
case OffscreenLane:
return OffscreenLane;
case DeferredLane:
return NoLanes;
default:
return lanes;
}
}
获取FiberRoot的下一个需要调度的lanes
export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes {
// root上待处理的lanes
const pendingLanes = root.pendingLanes;
// 如果为NoLanes直接return
if (pendingLanes === NoLanes) {
return NoLanes;
}
let nextLanes: Lanes = NoLanes;
// root上挂起的lanes
const suspendedLanes = root.suspendedLanes;
// root上已经被标记的lanes
const pingedLanes = root.pingedLanes;
// 通过& NonIdleLanes过滤掉所有IdleLanes
const nonIdlePendingLanes = pendingLanes & NonIdleLanes;
// 先执行nonIdle的lane,IdleLane是在所有其他lane都执行完成之后才能执行
if (nonIdlePendingLanes !== NoLanes) {
// 通过& ~ 的位计算来排除suspendedLanes(挂起的Lanes)
const nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes;
if (nonIdleUnblockedLanes !== NoLanes) {
// 从nonIdleUnblockedLanes中找到优先级最高的lane
nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes);
} else {
// 如果排除挂起的之后为空,就从挂起的中找到优先级最高的lane
const nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes;
if (nonIdlePingedLanes !== NoLanes) {
nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);
}
}
} else {
// 如果只有idleLanes就会走到这个逻辑,同样要排除suspendedLanes
const unblockedLanes = pendingLanes & ~suspendedLanes;
if (unblockedLanes !== NoLanes) {
nextLanes = getHighestPriorityLanes(unblockedLanes);
} else {
if (pingedLanes !== NoLanes) {
nextLanes = getHighestPriorityLanes(pingedLanes);
}
}
}
// 如果上述都找不到lanes,那就直接return
if (nextLanes === NoLanes) {
return NoLanes;
}
// 将wipLanes和我们找到nextLanes进行优先级的比较
if (
wipLanes !== NoLanes &&
wipLanes !== nextLanes &&
(wipLanes & suspendedLanes) === NoLanes
) {
const nextLane = getHighestPriorityLane(nextLanes);
const wipLane = getHighestPriorityLane(wipLanes);
// 如果nextLane优先级比wipLane高 return wipLanes
if (
nextLane >= wipLane ||
(nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes)
) {
return wipLanes;
}
}
return nextLanes;
}
一些lane的操作计算方法
// 是否有交集
export function includesSomeLane(a: Lanes | Lane, b: Lanes | Lane): boolean {
return (a & b) !== NoLanes;
}
// 是否是子集
export function isSubsetOfLanes(set: Lanes, subset: Lanes | Lane): boolean {
return (set & subset) === subset;
}
// 合并两个lane
export function mergeLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {
return a | b;
}
// 排除某个lane
export function removeLanes(set: Lanes, subset: Lanes | Lane): Lanes {
return set & ~subset;
}
// 两个lane相交
export function intersectLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {
return a & b;
}
和scheduler中优先级的关联
react中是使用scheduler库对任务进行的调度,scheduler有自己的优先级,而lane就代表来react中任务的优先级,那么lane和scheduler中的优先级如何对应上呢,如下:
将lanes转换成事件优先级:
export const NoEventPriority: EventPriority = NoLane;
export const DiscreteEventPriority: EventPriority = SyncLane;
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
export const DefaultEventPriority: EventPriority = DefaultLane;
export const IdleEventPriority: EventPriority = IdleLane;
// 优先级比较方法
export function isHigherEventPriority(
a: EventPriority,
b: EventPriority,
): boolean {
return a !== 0 && a < b;
}
// 将lanes转换成事件优先级
export function lanesToEventPriority(lanes: Lanes): EventPriority {
// 获取优先级最高的lane
const lane = getHighestPriorityLane(lanes);
// 如果lane优先级比DiscreteEventPriority高,则return DiscreteEventPriority
if (!isHigherEventPriority(DiscreteEventPriority, lane)) {
return DiscreteEventPriority;
}
// 其他同理
if (!isHigherEventPriority(ContinuousEventPriority, lane)) {
return ContinuousEventPriority;
}
if (includesNonIdleWork(lane)) {
return DefaultEventPriority;
}
return IdleEventPriority;
}
根据转换的事件优先级得到schedulerPriorityLevel,然后进行调度:
import {
ImmediatePriority as ImmediateSchedulerPriority,
UserBlockingPriority as UserBlockingSchedulerPriority,
NormalPriority as NormalSchedulerPriority,
IdlePriority as IdleSchedulerPriority,
cancelCallback as Scheduler_cancelCallback,
scheduleCallback as Scheduler_scheduleCallback,
now,
} from './Scheduler';
function scheduleTaskForRootDuringMicrotask(
root: FiberRoot,
currentTime: number,
): Lane {
// ...
let schedulerPriorityLevel;
// 根据转换的事件优先级得到schedulerPriorityLevel
switch (lanesToEventPriority(nextLanes)) {
case DiscreteEventPriority:
// DiscreteEventPriority对应ImmediateSchedulerPriority,值为1
schedulerPriorityLevel = ImmediateSchedulerPriority;
break;
case ContinuousEventPriority:
// ContinuousEventPriority对应UserBlockingSchedulerPriority,值为2
schedulerPriorityLevel = UserBlockingSchedulerPriority;
break;
case DefaultEventPriority:
// 其他同理
schedulerPriorityLevel = NormalSchedulerPriority;
break;
case IdleEventPriority:
schedulerPriorityLevel = IdleSchedulerPriority;
break;
default:
schedulerPriorityLevel = NormalSchedulerPriority;
break;
}
// 最后使用schedulerPriorityLevel进行任务调度
const newCallbackNode = scheduleCallback(
schedulerPriorityLevel,
performConcurrentWorkOnRoot.bind(null, root),
);
root.callbackPriority = newCallbackPriority;
root.callbackNode = newCallbackNode;
return newCallbackPriority;
}
}