A

什么是 React Fiber

2025-06-05 14:51

什么是 React Fiber

Fiber 是 React 16 以后新引入的架构,它不只是描述虚拟 DOM,而是将每一个节点抽象成“工作单元”,同时保存组件的状态、任务进度、优先级。

在 React 15 及以前,每次更新时 React 会重新生成一棵完整的虚拟 DOM 树,再与上一棵树进行 Diff,找出差异进行批量更新。这种方式有两个问题:

  1. 递归更新过程是同步执行,无法中断,树一旦大了,就会造成卡顿。
  2. 无法为不同更新分配优先级,比如用户输入与低优先级动画更新不能调度。

为了解决这个问题,React 16 开始引入Fiber 架构

Fiber 其实就是一个比“虚拟 DOM 节点”更强大的数据结构:

  • 它描述了当前节点(类型、props 等)。
  • 它保存了上一次渲染的节点(alternate)。
  • 它记录了这次更新的状态(是否需要插入、更新、删除)。
  • 它是调度和中断的最小工作单元

可以简单理解为:Fiber = 虚拟节点 + 更新状态 + 调度信息

Fiber 和虚拟 DOM 有什么区别?

很多人最容易混淆 Fiber 和虚拟 DOM。实际上它们是两个层面的概念:

  • 虚拟 DOM:只是一棵树,负责描述 UI 结构
    JAVASCRIPT
    { type: 'div', props: { className: 'header' }, key: null }
    它轻量,更新时每次都生成新的描述。
  • Fiber:是一种带有指针和状态的工作单元,既负责描述,也记录“进度”,支持中断和恢复。
    JAVASCRIPT
    { type: 'div', // 节点类型 stateNode: 真实 DOM 或组件实例, // 真实节点引用 return:Fiber, // 父节点指针 child: 第一个子 Fiber, // 第一个子节点指针 sibling: 下一个兄弟 Fiber, // 下一个兄弟节点指针 alternate: 上一次的 Fiber, // 上一次渲染的 Fiber 指针(用于对比) flags: 本次更新需要执行的操作 // 副作用标记 }
    Fiber 树结构是带链表指针的虚拟 DOM 树,React 基于它实现了调度、优先级控制和可中断渲染。

为什么 Fiber 要用链表指针?

在 React 15 中,Diff 和更新过程是靠递归实现的。递归调用依赖调用栈来维护上下文。 这样有两个缺点:

  • 递归过程同步且不可中断,会阻塞主线程。
  • 中间状态都存储在调用栈,React 无法灵活管理任务调度。 Fiber 将树改造为带有指针的链表结构,包含:
  • child: 指向第一个子节点;
  • sibling: 指向下一个兄弟;
  • return: 指向父节点; 这样设计的好处是:
  • React 不依赖调用栈,而是通过指针灵活遍历 Fiber 树。
  • 可以在任何时刻暂停遍历,保存当前 Fiber 节点状态,稍后恢复继续。
  • 支持实现 React 的时间切片(Time Slicing)并发渲染(Concurrent Rendering)

Fiber树 ≈ 带链表指针的虚拟DOM树。 这样,每个Fiber就是一个“最小可调度工作单元”。

图片加载中...
图表示意图

Fiber 的核心价值

为什么 React 要做这么复杂的设计?主要是为了解决三件事:

  1. 中断和恢复
    • 将更新任务拆分为最小工作单元 Fiber。
    • 每处理一个 Fiber,都可以暂停让出时间给浏览器。
    • 避免主线程长时间阻塞,保证 UI 流畅。
  2. 优先级调度
    • 每个Fiber携带 lanes(优先级)
    • 高优先级任务(如用户输入)先执行,低优先级任务(动画、日志)可延后。
    • React 18 进一步强化优先级调度,实现并发模式。
  3. 双缓存机制
    • 维护两棵 Fiber 树:current 指向已渲染的 Fiber 树,workInProgress 指向正在构建的新 Fiber 树。
    • 更新时先在 workInProgress 树上操作,更新完成后整体切换为新的树。
    • 这样避免更新过程直接影响当前渲染,保证一致性。

可以理解为: React Fiber 让“描述”和“执行”完全融合,也让更新过程变得可中断、可恢复、可调度。

Fiber树是如何生成的?

在了解React Diff之前,我们先要明白:Fiber树不是一次性生成,而是在渲染时动态创建和更新的。React 16+ 的整个更新过程,分为两个阶段:

  1. 调和阶段(Reconciliation / Render Phase)
    • 主要目标:
      • 创建新的 Fiber 树
      • 复用旧的 Fiber 节点
      • 比对新旧树,标记差异
    • 这个阶段可以被中断,也可以多次执行(支持时间切片)
    • 最后生成一棵工作中的Fiber树 (workInProgress)
  2. 提交阶段(Commit Phase)
    • 把收集的副作用一次性提交到DOM
    • 分为三步:
      • beforeMutation(快照阶段)
      • mutation(执行DOM操作)
      • layout(执行生命周期)
    • 这个阶段不能中断,必须同步执行。

一句话理解:调和阶段负责「计划」,提交阶段负责「落实」。


Fiber树的双缓存机制

React在更新时,实际上会同时维护两棵Fiber树:

  1. current Fiber树

    • 当前屏幕上渲染的那一棵
    • 存储「上一次渲染的状态」
  2. workInProgress Fiber树

    • 本次更新要生成的新Fiber树
    • 所有Diff、状态更新、优先级,都在这里操作
    • 最终提交后,这棵树会变成新的current
这种模式叫做双缓存(Double Buffering)
图片加载中...
图表示意图
为什么要这么做?
  • React需要先在内存里把新的Fiber树准备好
  • 等所有比对都完成,再一次性把变更提交
  • 避免在「生成树」过程中去操作DOM,保证一致性

Fiber树的生成流程

整个Fiber树的生成采用深度优先遍历(DFS),主要分两步:

  1. beginWork
    • 进入节点,处理当前更新逻辑
    • 判断要不要复用旧Fiber
    • 创建新的子Fiber
    • 返回下一个要处理的子Fiber
  2. completeWork
    • 子节点遍历完成后回到当前节点
    • 确定副作用(插入、更新、删除)
    • 把副作用链表传给父节点 整个过程可以这样理解:

「先往下创建树,回溯时把工作都收集好。」 Fiber树的生成过程是基于深度优先遍历,由两个核心函数驱动:

  • beginWork:处理当前 Fiber 节点,生成或复用子 Fiber。
  • completeWork:当所有子 Fiber 处理完毕后,完成当前 Fiber 的副作用收集。 这个过程类似于递归遍历一棵树:
  1. 调用 beginWork,尝试生成当前节点的子 Fiber,返回第一个子节点 Fiber。
  2. 如果有子节点,则继续递归 beginWork
  3. 如果没有子节点或者子节点处理完成,则回溯执行 completeWork,标记本节点需要的副作用。
  4. 回溯时,如果当前节点有兄弟节点,切换去处理兄弟节点的 beginWork
  5. 直到回溯到根节点,整个 Fiber 树构建完成。
JAVASCRIPT
function performUnitOfWork(fiber) { // 处理当前Fiber,创建/复用子Fiber const next = beginWork(fiber); if (next !== null) { // 递归往下遍历子节点 return next; } // 没有子节点或子节点已处理完,开始回溯 let node = fiber; while (node !== null) { completeWork(node); // 标记副作用 if (node.sibling !== null) { // 如果有兄弟节点,处理兄弟节点 return node.sibling; } node = node.return; // 回到父节点继续回溯 } return null; // 整棵树遍历完成 }

这段代码体现了 Fiber 树的深度优先遍历和回溯过程,保证每个节点的副作用能被完整处理并传递。


flags 标记的副作用

每个 Fiber 节点有一个 flags 字段,表示本次更新需要执行的操作类型:

  1. Placement:节点需要插入到 DOM。
  2. Update:节点属性或状态更新,需要修改 DOM。
  3. Deletion:节点需要从 DOM 删除。 React 在提交阶段会根据 flags 批量执行这些操作,保证 DOM 的高效更新。

总结

React Fiber 是对传统虚拟 DOM 的重构与升级,它将渲染过程拆分为可中断的最小任务单元,支持优先级调度和时间切片,极大提升了 React 的响应能力和用户体验。 通过 Fiber 树,React 能够灵活地控制渲染进度,实现并发渲染,保证高优先级任务优先执行,并且维护双缓存机制保证 UI 的一致性。 Fiber 是 React 现代架构的核心,理解它有助于深入掌握 React 的更新原理和性能优化。