Open astak16 opened 1 year ago
pendingLanes
,如果有,说明有高优先级的更新需要处理。pendingLanes
中是否有未阻塞的 lanes
,如果有,说明有可以立即渲染的更新。lanes
,那么检查是否有被唤醒的 lanes
,如果有,说明有可以恢复渲染的更新。pendingLanes
,那么说明只剩下闲置的更新,这些更新可以延迟处理。lanes
。getHighestPriorityLanes
函数来获取最高优先级的 lanes
,赋值给 nextLanes
。1 - 3
对应的是高优先级任务
5
对应的是低优先级的任务
高优先级任务和低优先级的任务做的事情是一样的:
都是先检查有没有未阻塞的任务,再检查有没有被唤醒的任务
// 判断是否有高优先级任务
// pendingLanes & NonIdleLanes 作用是:
// - 查看 pendingLanes 和 NonIdleLanes 之间有没有相同位为 1 的任务,如果有说明,有高优先级任务
const nonIdlePendingLanes = pendingLanes & NonIdleLanes;
// 高优先级任务
if (nonIdlePendingLanes !== NoLanes) {
// 判断是否有被挂起的 lanes
// nonIdlePendingLanes & ~suspendedLanes 作用是:
// - 将 suspendedLanes 从 nonIdlePendingLanes 中删除,如果 suspendedLanes 中有某一位为 1,那么 nonIdlePendingLanes 中的该位也会被置为 0
// - 如果删除了 suspendedLanes 后,nonIdlePendingLanes 仍然不为 0,说明还有阻塞的 lanes
const nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes;
// 有(未阻塞的 lanes)
if (nonIdleUnblockedLanes !== NoLanes) {
// 找到最高优先级的 lanes
nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes);
} else {
// 没有(未阻塞的 lanes)
// 判断是否有被唤醒的 lanes
// nonIdlePendingLanes & pingedLanes 作用是:
// - 查看 nonIdlePendingLanes 和 pingedLanes 之间有没有相同位为 1 的任务,如果有说明,有被唤醒的 lanes
const nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes;
// 有被唤醒的 lanes
if (nonIdlePingedLanes !== NoLanes) {
// 找到最高优先级的 lanes
nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);
}
}
} else {
// 低优先级任务
// 闲置的 pendingLanes 中 是否有未阻塞的 lanes
const unblockedLanes = pendingLanes & ~suspendedLanes;
// 有(未阻塞的 lanes)
if (unblockedLanes !== NoLanes) {
// 找到最高优先级的 lanes
nextLanes = getHighestPriorityLanes(unblockedLanes);
} else {
// 没有(未阻塞的任务)
// 闲置的 pingedLanes 中是否有被唤醒的 lanes
// 有被环境的 lanes
if (pingedLanes !== NoLanes) {
// 找到最高优先级的 lanes
nextLanes = getHighestPriorityLanes(pingedLanes);
}
}
}
比较当前工作的 lanes
和下一个要工作的 lanes
wipLanes
和 nextLanes
不一致,并且没有被挂起的 lanes
wipLane
优先级比 nextLane
优先级高,或者 wipLane
是过渡优先级,而 nextLane
是默认优先级wipLanes
// 如果当前工作的 lanes 中和 nextLanes 不一致,并且没有被挂起的 lanes
if (
wipLanes !== NoLanes &&
wipLanes !== nextLanes &&
(wipLanes & suspendedLanes) === NoLanes
) {
// 从 nextLanes 中找出优先级最高的 lane
const nextLane = getHighestPriorityLane(nextLanes);
// 从 wipLanes 中找出优先级最高的 lane
const wipLane = getHighestPriorityLane(wipLanes);
// 如果 nextLane 比 wipLane 的值要大,或者 nextLane 是默认优先级而 wipLane 是过渡优先级,将返回 wipLanes
if (
nextLane >= wipLane ||
(nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes)
) {
return wipLanes;
}
}
在同步模式下,连续输入事件的优先级会被合并一个默认优先级,以保证输入框的响应和体验
如果不合并默认优先级,那么连续输入事件的优先级可能会被其他更高的优先级打断,导致输入框的内容不同步或者丢失
// 如果当前的模式是并发模式,并且允许默认并发,那么就不改变 nextLanes
// 否则是否判断 nextLanes 中是否有 InputContinuousLane,如果有,就将 pendingLanes 中的 DefaultLane 加入到 nextLanes 中
if (
allowConcurrentByDefault &&
(root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode
) {
} else if ((nextLanes & InputContinuousLane) !== NoLanes) {
nextLanes |= pendingLanes & DefaultLane;
}
如果存在 entangledLanes
,将 entangledLanes
中的 lane
也加入到 nextLanes
中
const entangledLanes = root.entangledLanes;
if (entangledLanes !== NoLanes) {
const entanglements = root.entanglements;
// nextLanes 中是否有 entangledLanes 中的 lane
let lanes = nextLanes & entangledLanes;
while (lanes > 0) {
// lanes 中第一位为 1 的 index(从右往左)
// 举例:lanes = 0b0000000000000000000000000001010,index = 3
const index = pickArbitraryLaneIndex(lanes);
// 左移 index 位,得到 lane
const lane = 1 << index;
// 从 entanglements 中取出 entangledLanes,和 nextLanes 进行或运算,在赋值给 nextLanes
nextLanes |= entanglements[index];
// 将 lane 从 lanes 中移除
lanes &= ~lane;
}
}
react
是如何知道 entangledLanes
在 entanglements
什么位置呢?
比如现在 entangledLanes = 0b0000000000000000000000000001010
react 通过 pickArbitraryLaneIndex(lanes)
可以算出最左边的 1
的位置:
0b0000000000000000000000000000010
对应的 index = 1
0b0000000000000000000000000001000
对应的 index = 3
所以 entanglements
中是这么存储的 [0, 0b0000000000000000000000000000010, 0, 0b0000000000000000000000000001000]
react-reconciler
中 getNextLanes 函数作用是:在
react
一次任务调度中,找出优先级最高的任务 大概分为4
步:wipLanes
和nextLanes
lanes
其中
1/3/4
都是会改变nextLanes
,2
直接return wipLanes