理解 React Fiber 的工作单元结构 是掌握 Fiber 架构和调度机制的关键之一。Fiber 的设计将原来的递归更新流程变成了可中断、可恢复的链式遍历结构,每一个组件渲染时都会生成一个 Fiber 工作单元。
🧱 一、什么是 Fiber 工作单元(Fiber Node)?
Fiber 节点是 React 中用于表示组件的最小工作单元,它是一种数据结构,用来描述:
- 当前组件是什么?
- 有哪些 props?
- 它的子节点是什么?
- 它的上一次状态是什么?
- 它的更新进度如何?
每个 React 组件或元素都会对应一个 Fiber 节点。
🧩 二、Fiber 节点的结构(核心字段)
typescript
interface FiberNode {
tag: WorkTag; // 表示类型,如 FunctionComponent、ClassComponent 等
type: any; // 组件类型(函数/类/HTML标签名)
key: null | string; // 用于列表 diff 的 key
stateNode: any; // 对于原生组件,是 DOM;对于类组件,是 class 实例
return: FiberNode | null; // 指向父节点
child: FiberNode | null; // 指向第一个子节点
sibling: FiberNode | null; // 指向下一个兄弟节点
index: number; // 位置索引(用于 diff)
pendingProps: any; // 本次更新传入的 props
memoizedProps: any; // 上一次渲染使用的 props
memoizedState: any; // 当前的 state
updateQueue: UpdateQueue | null; // 待处理的更新
alternate: FiberNode | null; // 指向旧的 Fiber(实现双缓冲)
flags: Flags; // 标记副作用类型(比如 Placement、Update、Deletion)
subtreeFlags: Flags; // 子树的副作用标记合集
}
📐 三、Fiber 节点之间的结构关系:三叉链表
Fiber 树不是传统的 DOM 树(树结构),而是一个三叉链表结构:
kotlin
return
↑
Parent
↓
┌─────────────┐
child → sibling → sibling
这种设计让 Fiber 树在遍历时不需要递归,而是用循环实现(节省堆栈空间):
child
: 第一个子节点sibling
: 兄弟节点return
: 父节点
🎭 四、tag 字段:表示 Fiber 类型
ini
export const FunctionComponent = 0;
export const ClassComponent = 1;
export const HostComponent = 5; // 原生 DOM 节点(div、span)
export const HostText = 6; // 文本节点
export const HostRoot = 3; // 根节点(ReactDOM.createRoot)
通过 tag
,React 在渲染每个节点时知道该怎么处理这个组件。
🔁 五、双缓冲机制(alternate)
React 每次更新不会修改当前正在使用的 Fiber 树,而是创建一棵新的 Fiber 树(workInProgress) 。两个版本之间通过 alternate
指针互相指向。
ini
current.alternate === workInProgress
workInProgress.alternate === current
这样可以:
- 实现"增量更新":不必一次性修改整棵树
- 可以在渲染中断时保留上次渲染结果
- 在 commit 阶段统一更新 DOM
⚙️ 六、副作用标记系统(flags)
Fiber 节点上会打上各种"副作用"标记(即需要做什么更新操作),用于 commit 阶段统一处理。
常见的 flags:
ini
export const NoFlags = 0b00000000000000000000;
export const Placement = 0b00000000000000000010; // 新节点插入
export const Update = 0b00000000000000000100; // 属性或状态更新
export const Deletion = 0b00000000000000001000; // 删除节点
commit 阶段只需要遍历 Fiber 树,根据 flags 执行对应 DOM 操作。
📊 七、每个 Fiber 单元的生命周期(创建 → 渲染 → 提交)
- 创建 Fiber 节点 :由 JSX → React Element → Fiber 节点(在
beginWork
中) - 收集副作用 :在
completeWork
阶段,根据节点变化记录 flags - 提交副作用 :在
commitRoot
阶段统一处理(插入、更新、销毁)
🧮 示例:一个简单组件的 Fiber 结构
javascript
function App() {
return (
<div>
<h1>Hello</h1>
</div>
);
}
对应 Fiber 结构如下(简化):
php
Fiber (App) tag: FunctionComponent
│
└── Fiber (div) tag: HostComponent
│
└── Fiber (h1) tag: HostComponent
│
└── Fiber ("Hello") tag: HostText
每个 Fiber 节点都有 return
(指向上一级)、child
、sibling
等指针,组成链式结构。
🎯 总结:Fiber 单元结构的价值
功能 | 描述 |
---|---|
遍历性能 | 三叉链表 + 循环遍历,避免递归栈 |
支持中断 | 每个 Fiber 是一个最小调度单元,可以中断恢复 |
双缓存 | alternate 实现前后版本对比 |
精准更新 | flags 标记副作用,提升效率 |
灵活调度 | 可组合的调度机制:优先级、延迟、异步 |