Skip to content

React Fiber 的概念与工作原理 ​

在 React 中, 每个函数组件的实例并不直接是一个 Fiber, 但每个组件确实都有一个与之对应的 Fiber 节点. Fiber 是 React 用来管理和调度组件渲染的内部机制. React Fiber 引入了一种全新的架构, 帮助解决了之前同步渲染带来的性能问题. 让我们详细说明 Fiber 的历史背景、数据结构及工作原理.

React Fiber 的历史背景与产生原因 ​

在 React Fiber 出现之前, React 使用的是同步渲染模型, 这意味着每次更新时, React 会一次性从头到尾完成整个组件树的渲染. 如果组件树庞大或者渲染操作复杂, 这会导致 UI 卡顿, 用户体验变差.

React Fiber 产生的主要原因是为了解决以下问题:

  1. 性能问题:同步渲染无法分割渲染任务, 导致 React 的 UI 响应速度下降, 尤其是在复杂场景下.
  2. 响应性:React Fiber 通过引入增量渲染, 让渲染过程可以分成小任务, 在任务之间可以让出控制权给浏览器, 处理更高优先级的任务 (如用户输入) , 从而提升应用的响应速度.

什么是 Fiber? ​

Fiber 是 React 16 引入的一种基于链表的数据结构, 用来表示组件树中的每个组件. 它使 React 能够将渲染工作分解为多个小任务, 并允许在执行这些任务的过程中暂停、继续或丢弃它们. Fiber 实现了并发渲染和任务优先级调度, 从而提高了渲染的灵活性和性能.

函数组件与 Fiber 的关系 ​

在 React 的渲染流程中, 每个组件 (无论是函数组件还是类组件) 都会有一个对应的 Fiber 节点. Fiber 节点记录了该组件的状态、DOM 信息以及与组件渲染相关的其他元数据.

  • 函数组件本质上是一个普通的 JavaScript 函数, 没有实例化 this 对象. 因此, React 通过 Fiber 节点来存储和管理与函数组件相关的状态和生命周期.
  • 每个函数组件在每次渲染时, React 都会创建或更新与之对应的 Fiber 节点, Fiber 节点是 React 内部调度渲染的关键部分.

Fiber 节点中的关键信息 ​

每个 Fiber 节点代表一个组件, 并包含以下关键信息:

  • tag: 表示 Fiber 组件的类型,例如 Function 组件和 class 组件。
  • key: 组件的 key 属性,用于在 diff 算法中帮助识别组件的唯一性。
  • elementType: 代表组件的类型,特定情况下(如被 React.memo 包裹时)可能与 type 不同。
  • type: 指向组件的类型,对于函数组件是函数本身,对于类组件是类,对于 DOM 节点是其 tagName。
  • stateNode: Fiber 对应的实际 DOM 节点的引用。
  • return: 指向父 Fiber 节点,形成 Fiber 树的链接关系。
  • child: 指向子 Fiber 节点,维护组件树的层级结构。
  • sibling: 指向同一层级的下一个兄弟 Fiber 节点。
  • index: 当前节点在兄弟节点中的位置索引。
  • pendingProps: 当前组件的属性,表示本次渲染的最新属性。
  • memoizedProps: 指向最近一次使用的 props,用于比较和更新。
  • updateQueue: 保存需要处理的更新信息的队列。
  • memoizedState: 组件的状态,用于保存当前状态值。
  • dependencies: 指向依赖于该组件的其他组件或数据。
  • mode: 表示组件运行的模式(并发模式或遗留模式),影响组件的更新方式。
  • flags: 当前组件的标记位,表示需要执行的操作(如更新、删除等)。
  • subtreeFlags: 当前组件子树的标记位,用于跟踪子组件的状态。
  • deletions: 保存需要删除的 Fiber 对象链表,以便在提交时处理。
  • lanes: 当前组件的调度优先级,用于调度更新任务。
  • childLanes: 子组件的优先级,表示在当前 Fiber 节点下的子组件的优先级。
  • alternate: 指向该 Fiber 在另一次更新时对应的 Fiber,允许 React 在更新过程中重用 Fiber 结构。

Fiber 如何管理函数组件 ​

函数组件没有类组件中的实例, 因此 React 通过 Fiber 来管理函数组件的状态、Hooks 等信息:

  • useState 与 Fiber:useState 会将状态信息记录在与该组件对应的 Fiber 节点中, 每次状态更新时, React 会更新该节点.
  • useEffect 与 Fiber:useEffect 的副作用函数同样会被绑定到当前的 Fiber 节点上, 等待适当时机执行.

React Fiber 的工作原理 ​

React 的渲染分为两个阶段:协调阶段 (Render Phase) 和 提交阶段 (Commit Phase).

  1. 协调阶段 (Render Phase)
    • 在这个阶段, React 会遍历 Fiber 树, 比较新旧虚拟 DOM, 创建新的 Fiber 节点, 并标记需要更新的部分. 这个阶段是可中断的, React 可以在任务之间暂停, 处理更高优先级的任务.
  2. 提交阶段 (Commit Phase)
    • 提交阶段是不可中断的, React 会将协调阶段收集到的更改应用到真实 DOM 上, 并执行 useLayoutEffect 等同步副作用.

React Fiber 的关键特性 ​

  • 任务优先级调度:React Fiber 根据任务的优先级, 灵活安排更新任务, 确保更紧急的任务 (如用户输入) 优先处理.
  • 异步渲染:通过将渲染工作分割成更小的任务, React 可以在多个帧中完成渲染, 避免主线程长时间被占用.
  • 时间分片:React Fiber 可以将大任务拆分为时间片, 在每个时间片内执行一部分任务, 使得 UI 渲染更流畅.

总结 ​

  • 每个 React 函数组件与一个 Fiber 节点密切关联, 该节点用于调度和管理组件的渲染过程.
  • Fiber 是 React 内部的核心数据结构, 追踪组件的状态、属性、DOM 引用等信息.
  • React Fiber 通过分割渲染任务、调度任务优先级, 优化了复杂 UI 场景下的性能和响应速度.

React Fiber 的引入大幅提升了 React 在复杂应用中的性能表现, 同时为实现并发渲染奠定了基础.