React Lane 模型

Lane 是 React 中用于表示任务优先级的概念。优先级分为高优先级与低优先级。

调度流程概览

  1. 编写代码绑定事件时,根据不同的事件,React 会给它分配一个 lane。
  2. 触发该事件产生更新时,可以获取到这个事件的优先级,把产生的更新放到对应 Fiber 的更新队列中。
  3. 更新产生后,对应 Fiber 节点产生变化,开始新一轮调度。我们要自底向上更新优先级,通过合并 Fiber 的 lane 和父节点的 childLanes,这些更新最后会被收集到 Fiber root 的 pendingLanes 中,然后将事件的触发时间更新到 eventTimes 中。
  4. 任务调度开始时,先判断 pendingLanes 中有没有过期的任务。如果有任务过期,将它放到 expiredLanes 紧急队列中尽快调度防止饥饿;如果任务没设置过期时间,就根据它的 lane 设置过期时间(优先级越高过期越快)。
  5. 之后根据 expiredLanes、pendingLanes 以及 suspendedLanes 取得当前最紧急的任务,根据优先级判断当前最紧急的任务能否打断现有任务的执行(高优先级抢占),然后根据任务的优先级决定用什么模式开启任务。我们把计算得到的优先级最高的一批任务放到 subtreeRenderLanes 中,作为这次调度的执行任务。
  6. 进行一次 diff 操作,根据对应 Fiber 上的 lanes 是否在 subtreeRenderLanes 中判断能否直接复用。
  7. 如果不能复用,则调用 processUpdateQueue 处理 Fiber 上的更新队列,根据 fiber 上的 lanes 是否在 subtreeRenderLanes 中判断是否要执行此更新。如果一个任务更新了,就删除对应的 lane。
  8. diff 流程结束后,进入 commit 阶段:将每个节点和孩子节点的 lanes 合并,计算出还没有更新的 lanes 和已经更新的 lanes,从 root 中删除已经更新的 lanes,把未更新的 lanes 作为下一次调度的任务,然后开始新的调度,循环往复,直到所有任务运行完毕。

Lane 的种类

React 中有多种类型的 Lanes,每种 Lane 都有不同的优先级和用途:

  • Sync:此 Lane 用于处理同步更新(用户在当前任务中触发的更新),具有最高的优先级,将会立即执行。
  • Input:此 Lane 用于处理用户交互触发的更新,例如点击、滚动或输入。
  • Animation:此 Lane 用于处理动画更新,例如 CSS 动画或第三方动画库的动画。
  • Paint:此 Lane 用于处理需要重绘屏幕的更新,例如更改 DOM 元素的样式或文本。
  • Passive:此 Lane 用于处理低优先级的更新,例如更新后台数据或执行计时器回调。

来源整理自:vue3js.cn 面试官系列