人人都会AI编程

双缓存技术:current 树与 workInProgress 树

更新时间:2026-07-11

双缓存技术是 React Fiber 架构中一项关键的设计,用于在协调(Reconciliation)过程中实现可中断的渲染。它通过在内存中维护两棵 Fiber 树,确保渲染过程的中间状态不会直接影响当前屏幕上显示的界面,从而支持并发渲染和时间切片(Time Slicing)。

为什么需要双缓存

在早期的 Stack Reconciler 中,React 使用递归方式同步遍历组件树,一旦开始就会一次性完成整个更新。这种方式简单直接,但存在明显缺陷:

  • 无法中断:大型组件的渲染会长时间占用主线程,导致页面卡顿。
  • 没有中间状态管理:如果在更新过程中出现高优先级任务(如用户输入),无法切换,只能等当前更新完成。

Fiber 架构的解决方案之一是让渲染可以在任何时候暂停和恢复,这就需要一套特殊的机制来隔离“正在计算的新界面”和“当前显示的旧界面”。双缓存技术由此诞生。

两棵 Fiber 树的角色

在 React 的内部实现中,每次更新都会同时存在两棵 Fiber 树:

  1. current 树
  • 代表当前屏幕上显示出来的 UI 对应的 Fiber 结构。
  • 每个 Fiber 节点通过 alternate 属性与另一棵树中对应的节点连接。
  • 当没有任何更新发生时,React 只维护这一棵树。
  1. workInProgress 树
  • 代表正在内存中计算和构建的新 UI 对应的 Fiber 结构。
  • 在 Render 阶段被逐步创建和填充,是“草稿”状态的界面描述。
  • 构建完成后,在 Commit 阶段一次性替换为新的 current 树,并渲染到屏幕。

这两棵树的结构完全相同,只是代表不同的渲染状态。每个节点都有一个 alternate 属性,指向另一棵树中对应的节点。这种设计让 React 能够随时在两个版本之间切换,从而支持中断、恢复甚至放弃更新。

双缓存的工作流程

一次状态更新触发后,React 会执行以下步骤:

第一步:开始更新,创建 workInProgress 树
React 从 current 树的根节点开始,为每个节点创建一个对应的 workInProgress 节点(通过 alternate 互相引用)。如果某个节点之前已经存在 workInProgress 节点(例如上次更新被中断),就会复用而非新建。

第二步:Render 阶段(可中断)
在这个阶段,React 会遍历 Fiber 树,调用组件函数,生成新的虚拟 DOM,并对比新旧节点,标记需要执行的 DOM 操作(Placement、Update、Deletion 等)。所有这些工作都在 workInProgress 树上进行,current 树保持不变,屏幕上显示的仍然是旧界面。

这个阶段可以被高阶任务中断。当中断发生时,workInProgress 树会保留已计算的部分,主线程被释放去处理用户点击、动画等高优先级任务。稍后恢复时,React 可以从中断点继续完成 workInProgress 树的构建。

第三步:Commit 阶段(不可中断)
Render 阶段完成后,workInProgress 树包含了新的 Fiber 结构和全部副作用(Effects)。此时进入 Commit 阶段,React 会将 workInProgress 树的变更一次性应用到真实 DOM 上,然后执行 useEffect 等布局副作用。

关键的一步:Commit 完成后,workInProgress 树变为新的 current 树。原来的 current 树则在下一次更新中被复用(或垃圾回收)。至此双缓存的一次循环完成。

具体示例

假设有一个计数器组件,点击按钮后 count 从 0 变为 1。流程如下:

  1. 初始状态:current 树描述 count = 0 的界面,目前显示在屏幕上。
  2. 点击触发更新:React 创建 workInProgress 树,开始 Render 阶段。
  3. Render 阶段:调用 Counter 组件函数(或协调类组件实例),得到 count = 1 的新虚拟 DOM,在 workInProgress 树上标记“文本内容需要更新”。
  4. Commit 阶段:React 将 workInProgress 树的变更提交到 DOM,更新文本。
  5. 交换:提交完成后,此 workInProgress 树成为新的 current 树,旧的 current 树被回收或留待复用。

如果在 Render 阶段过程中,用户触发了其他更高优先级的更新(例如输入框输入),React 可以中断当前 workInProgress 树的构建,去处理新的更新。等输入处理完毕后,再决定继续或放弃之前的计数器更新。

双缓存的实际意义

  • 无闪烁的中断渲染:由于 current 树始终保留着正在显示的界面,workInProgress 的中间状态永远不会暴露给用户,确保了视觉的稳定性。
  • 资源复用:通过 alternate 引用,React 可以在多次更新间复用 Fiber 节点,减少内存分配和垃圾回收的压力。
  • 并发模式的基础:双缓存使得 React 能够实现“渲染暂停、恢复、丢弃”,是并发渲染(Concurrent Rendering)的基石。
  • 错误恢复:如果 workInProgress 树在构建过程中抛出错误,React 可以直接丢弃损坏的树,回退到 current 树,结合错误边界(Error Boundary)显示降级 UI。

常见误区

  • 双缓存不是“两个虚拟 DOM”:虚拟 DOM 是 React 元素(JSX)的结果,而 Fiber 树是包含了更多元信息(优先级、副作用、与实例的关联)的完整工作单元。双缓存指的是 Fiber 树的双份,而非虚拟 DOM 的两份。
  • 双缓存并不会增加内存开销的一倍:因为同一时刻只有一棵 workInProgress 树正在构建中,而且大量数据通过交替引用共享,实际内存开销远小于两棵完整树的总和。

理解双缓存技术能帮助你更好地理解 React 内部的工作方式,尤其是在处理性能优化和调试复杂交互时,这种机制提供了“为什么可以做到不卡顿”的根本答案。