React Fiber 通过重新设计协调(Reconciliation)过程的底层架构,实现了可中断的异步渲染。以下是其核心实现原理:
1. Fiber 数据结构
每个 React 组件对应一个 Fiber 节点,形成链表树结构,包含以下关键信息:
- 组件类型(如
div、MyComponent) - 状态和 Props
- 指针:
child(第一个子节点)、sibling(下一个兄弟节点)、return(父节点) - 工作状态:
alternate(指向当前节点和正在构建的副本,用于双缓冲) - 副作用标记(如插入、更新、删除)
interface Fiber {
tag: WorkTag; // 组件类型(函数组件、类组件等)
key: string | null;
type: any; // 组件对应的DOM类型或构造函数
stateNode: any; // 对应的真实DOM或组件实例
pendingProps: Props; // 新Props
memoizedProps: Props; // 当前Props
memoizedState: any; // 当前State(如Hooks链表)
alternate: Fiber | null; // 指向另一棵树中的对应节点
effectTag: SideEffectTag; // 副作用标记(如Placement、Update)
nextEffect: Fiber | null; // 指向下一个有副作用的Fiber节点
// ...其他字段
}
2. 可中断的遍历机制
(1) 链表遍历替代递归栈
-
传统递归问题:递归调用栈不可中断,一旦开始必须执行到底。
-
Fiber 解决方案:将组件树转换为链表结构(通过
child、sibling指针),通过循环遍历(while)替代递归。function workLoop(deadline) { while (currentFiber && hasRemainingTime(deadline)) { currentFiber = performUnitOfWork(currentFiber); } if (!currentFiber) commitRoot(); // 提交变更 else requestIdleCallback(workLoop); // 继续下一次循环 }
(2) 时间分片(Time Slicing)
-
任务拆分:将渲染任务拆分为多个 工作单元(Unit of Work) ,每个单元对应一个 Fiber 节点的处理。
-
中断检查:在浏览器每一帧的 空闲时间(Idle Period) 执行任务,通过
requestIdleCallback(或 React 自研的 Scheduler)判断剩余时间:function performUnitOfWork(fiber) { // 1. 开始工作(如Diff比较、生命周期调用) beginWork(fiber); // 2. 如果有子节点,优先处理子节点 if (fiber.child) return fiber.child; // 3. 没有子节点则处理兄弟节点或回溯父节点 let nextFiber = fiber; while (nextFiber) { completeWork(nextFiber); if (nextFiber.sibling) return nextFiber.sibling; nextFiber = nextFiber.return; } } -
中断恢复:若时间不足,保存当前遍历位置(
currentFiber),下次从断点继续。
3. 双缓冲与副作用收集
-
双缓冲技术:通过
alternate属性维护两棵 Fiber 树:- Current Tree:当前已渲染的树。
- WorkInProgress Tree:正在构建的新树。
-
副作用列表:在遍历过程中收集需要更新的节点(通过
effectTag标记),形成单向链表(nextEffect),提交阶段一次性处理。
4. 优先级调度
React 根据更新来源(如用户交互、网络响应)分配不同优先级:
- Immediate:需立即处理(如输入事件)。
- UserBlocking:用户交互相关(如动画)。
- Normal:普通数据更新。
- Low:低优先级任务(如日志上报)。
- Idle:空闲时处理。
通过优先级调度,高优先级任务可中断低优先级渲染。
5. 示例:中断与恢复流程
-
初始状态:开始渲染组件树,遍历到 Fiber 节点 B。
A → B → C -
中断发生:用户点击按钮触发高优先级更新。
- React 暂停当前渲染,保存断点(当前处理到 B)。
- 优先处理点击事件的回调,生成新的更新。
-
恢复渲染:高优先级任务完成后,重新从断点(B)继续遍历,或根据新更新重新协调。
总结
| 机制 | 实现方式 |
|---|---|
| 数据结构 | 链表结构的 Fiber 节点,支持断点恢复。 |
| 任务拆分 | 将渲染拆分为可中断的工作单元,通过循环遍历替代递归。 |
| 时间分片 | 利用浏览器空闲时间执行任务,避免阻塞主线程。 |
| 双缓冲与副作用 | 通过两棵树和副作用列表保证渲染一致性。 |
| 优先级调度 | 动态调整任务优先级,确保交互响应性。 |
通过以上设计,React Fiber 实现了:
- 可中断渲染:避免长时间任务阻塞主线程。
- 增量渲染:逐步将更新应用到界面,提升流畅度。
- 并发模式支持:为未来功能(如 Suspense、并发渲染)奠定基础。