面试官又问我是否深入了解过 React Fiber?

6 阅读3分钟

什么是Fiber?

回答这个问题需要从三个方面来理解:

  • 是一种架构模式:Fiber架构。V16版本之前,React使用的 Stack 架构,V16发布之后使用的Fiber架构;
  • 是一种数据类型:描述虚拟DOM的JS对象。在上篇文章虚拟DOM中提到了React在Stack架构和FIber架构实现虚拟DOM的方式是不同的,V16之后,使用了Fiber节点组成的链表实现了虚拟DOM的描述对象。
  • 是一种调度单元:将整个渲染过程拆解为多个可中断、可优先级调度的“纤维”(Fiber)任务。

在上篇上篇文章虚拟DOM中也提到了虚拟DOM是描述对象是如何的, 现在就可以看看Fiber节点描述的虚拟DOM中是长什么样子的:

{
  type: ComponentType, // 组件类型(函数/类)
  key: string,         // 同级节点唯一标识
  child: Fiber,        // 第一个子节点
  sibling: Fiber,      // 下一个兄弟节点
  return: Fiber,       // 父节点
  pendingProps: Props, // 新传入的props
  memoizedProps: Props,// 上次渲染的props
  stateNode: Instance, // 组件实例或DOM节点
  effectTag: number,   // 标记副作用(如插入、更新、删除)
  // ...其他调度相关字段(优先级、状态等)
}

Fiber通过childsiblingreturn形成链表树,替代了原有的树形结构,实现非递归遍历。

为什么要出现Fiber?

我们知道React使用通过操作虚拟DOM进行页面视图的更新,当我们更新一个状态去触发更新时,React需要进行寻找该节点的位置,然后去更新它。

但是 Stack 架构基于递归的协调算法来更新虚拟DOM,我们知道JS的线程和渲染线程是在同一个线程中为互斥关系,当组件树庞大时,递归更新会长时间占用主线程,这个时候渲染层面的更新就不得不长时间地等待,界面长时间不更新,会导致页面响应度变差,用户可能会感觉到卡顿。这就是Fiber架构出现的原因,旨在支持任务的中断与恢复。

Fiber 双缓冲

双缓冲是为了提升视觉流畅性,工作原理类似于显卡的工作原理:

  1. 前缓冲区(Front Buffer) :当前屏幕显示的图像帧。
  2. 后缓冲区(Back Buffer) :后台计算新图像帧的临时区域。
  3. 互换机制:当后缓冲区完成新帧计算后,通过缓冲区交换(Swap) 瞬间替换前缓冲区内容。

这样达到效果是:一方面避免用户看到渲染中间态(如闪烁、撕裂);另一方面将耗时的渲染计算隐藏在后台,保证画面连续流畅。

React 将双缓冲思想深度融入 Fiber 中,通过双 Fiber 树实现无感知的平滑更新,具体实现:

  1. 双树共存

    • Current Tree:与当前 UI 完全对应的 Fiber 树,代表已渲染的视图状态。
    • WorkInProgress Tree:内存中构建的新 Fiber 树,承载下一次更新的计算任务。
  2. 树间关联

    • 每个 Fiber 节点通过 alternate 属性与另一棵树的对应节点互相引用:
// Current Fiber 节点
currentFiber.alternate = workInProgressFiber;
// WorkInProgress Fiber 节点
workInProgressFiber.alternate = currentFiber;

// 这种双向指针设计使得状态复用、增量更新成为可能。
  1. 渲染流程

    • 构建阶段:在 WorkInProgress Tree 上执行组件渲染、Diff 计算,生成副作用链表(Effect List)。
    • 提交阶段:锁定两棵树,将 WorkInProgress Tree 一次性切换为 Current Tree,同步更新 DOM。
    • 循环往复:完成提交后,旧的 Current Tree 转为新 WorkInProgress Tree 的初始状态。

双缓存可以让计算过程完全在内存中的 WorkInProgress Tree 完成,用户始终感知稳定的 Current Tree 视图,视觉上不会出现撕裂的效果。