第 22 章:Lane 优先级模型——31 条车道
第 5 章说 Scheduler 有五级优先级。但 React 内部需要更细的区分:同样是一个 setState,在 onClick 里调和在 useEffect 里调,紧迫程度不一样。所以 React 不用五级,而是用一套 31 位的位图模型,叫 Lane(车道)。
先记住这一句:Lane 就是一个 31 位的二进制数,每一位是一条"车道",数字越小(越靠低位)优先级越高。多条更新用或运算合并成
Lanes,取最高优先就找最低的 1。
一图流:31 条车道怎么分组
位图:为什么用二进制
ReactFiberLane.js 里,总车道数是 31(ReactFiberLane.js:40)。每个常量是一个二进制位:
export const SyncLane: Lane = 0b0000000000000000000000000000010; // 第 46 行
export const InputContinuousLane: Lane = 0b0000000000000000000000000001000;
export const DefaultLane: Lane = 0b0000000000000000000000000100000;
用位图的好处是所有优先级操作都是 O(1) 位运算:
- 合并多条更新:
mergeLanes(a, b) = a | b。一次点击里的多个 setState 各占一个位,|一下就到一起。 - 判断某条更新是否在里面:
(lanes & lane) !== 0。 - 取最高优先级:找最低位的 1,
getHighestPriorityLane用lanes & -lanes(lowestOneBit)直接拿到。
这三个操作在第 21 章的旅程里无处不在:requestUpdateLane 要一个位,scheduleUpdateOnFiber 把位写到 lanes,getNextLanes 决定这一轮渲染哪些位。
车道分组:从最急到最不急
按优先级从高到低,车道分成几组:
| 车道组 | bit 范围 | 用途 |
|---|---|---|
| Sync(第 46 行) | 1 | 同步更新,flushSync 用 |
| InputContinuous(第 50 行) | 3 | 输入类(onClick、onChange),Scheduler 的 UserBlocking |
| Default(第 53 行) | 5 | 普通 setState,Scheduler 的 Normal |
| Transition(第 61 行) | 8~23,16 条 | useTransition 里的低优先更新,每条 transition 一条车道 |
| Retry(第 93 行) | 24~27,4 条 | Suspense 挂起后的重试 |
| SelectiveHydration / Idle / Offscreen(101~108 行) | 28~30 | 水合、空闲任务、隐藏树 |
低位是"用户正等着看结果"的事(点击、输入),高位是"可以慢慢来"的事(低优先 transition、预加载)。lane 和 Scheduler 五级优先级之间有个换算:React 把 lane 映射成 Scheduler 的优先级再排队(第 5 章那个对接),lane 是 React 自己的"精确刻度",Scheduler 是"粗粒度执行器"。
并发怎么靠 lane 工作
lane 是第 23 章(并发渲染)的地基:一次渲染带着一组 lanes 开跑,中途来了更高优先级的 lane,就中断当前渲染,先渲染新 lane 那批。渲染完了检查还有没有更高优先的 lane,没有才 commit。getNextLanes 每次问"现在该跑哪些车道",答案就是这一轮 render 的路线图。
动手实验
- 看 requestUpdateLane:在
requestUpdateLane(ReactFiberLane.js 附近)打断点,分别从onClick和useEffect里setState,观察两次拿到的 lane 不同(前者 InputContinuous,后者 Default)。 - 看合并:一个事件里连调两次
setState,观察 fiber 的lanes变成两个位的或。 - 看取最高:在
getNextLanes打断点,同一批里混着 Sync 和 Default 的更新,看它是不是先挑了 Sync。
小结
- Lane 是 31 位位图,低 bit 高优先,所有操作是 O(1) 位运算。
- 分组:Sync / InputContinuous / Default / Transition×16 / Retry×4 / Idle / Offscreen。
mergeLanes(或)、getHighestPriorityLane(lowest bit)、getNextLanes(选路线图)。- lane 是 React 的精确刻度,Scheduler 是粗粒度执行器,两者换算对接。
- 下一步:lane 让"中断和恢复"成为可能,第 23 章看并发渲染。