Appearance
React Fiber 全面深度解析
- Fiber 详细介绍、核心原理与组成部分
- 调和/提交完整工作流程
- Fiber 与函数组件、Hooks 的关系
- Fiber 的中断恢复与优先级调度
- Fiber 数据视图更新渲染流程
- Fiber 与 Stack Reconcile 协调算法
- Fiber 全面总结
1. Fiber 详细介绍、核心原理与组成部分
1.1 什么是 Fiber
Fiber 是 React 16 引入的新的协调算法,它是 React 核心算法的重构。Fiber 的核心目标是实现增量渲染,将大型任务拆分成小任务单元,能够中断、恢复和复用渲染工作,使 React 能够更好地响应用户交互。
1.2 Fiber 的核心原理
1.2.1 核心思想
Fiber 的核心思想是将同步递归更新改为异步可中断更新:
- 时间切片(Time Slicing):将渲染工作拆分成多个小任务单元
- 优先级调度(Priority Scheduling):不同任务有不同的优先级,高优先级任务可以打断低优先级任务
- 可中断与恢复:任务可以被中断,之后可以从中断点恢复执行
- 双缓冲机制:使用 current 树和 workInProgress 树实现无中断更新
1.2.2 核心原理图
┌─────────────────────────────────────────────────────────────────┐
│ React Fiber 核心原理 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ 用户交互 │
│ 状态更新等 │
└──────┬───────┘
│
▼
┌──────────────┐
│ 创建更新任务 │
│ 分配优先级 │
└──────┬───────┘
│
▼
┌──────────────────────┐
│ 调度器 (Scheduler) │
│ - 任务队列管理 │
│ - 优先级排序 │
│ - 时间切片控制 │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ 协调阶段 (Reconcile) │
│ - 可中断 │
│ - 构建 Fiber 树 │
│ - Diff 算法 │
│ - 标记副作用 │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ 提交阶段 (Commit) │
│ - 不可中断 │
│ - 执行副作用 │
│ - 更新 DOM │
└──────────────────────┘1.3 Fiber 的组成部分
1.3.1 Fiber 节点的数据结构
每个 Fiber 节点对应一个 React 元素,包含以下关键属性:
javascript
function FiberNode(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
// ========== 实例属性 ==========
this.tag = tag; // Fiber 类型(函数组件、类组件、DOM元素等)
this.key = key; // React key
this.elementType = null; // 元素类型
this.type = null; // 函数组件/类组件的类型
this.stateNode = null; // 对应的真实 DOM 节点或组件实例
// ========== Fiber 树结构 ==========
this.return = null; // 父 Fiber 节点
this.child = null; // 第一个子 Fiber 节点
this.sibling = null; // 下一个兄弟 Fiber 节点
this.index = 0; // 在父节点中的索引
// ========== 属性相关 ==========
this.pendingProps = pendingProps; // 新的 props
this.memoizedProps = null; // 上一次渲染的 props
this.updateQueue = null; // 更新队列
this.memoizedState = null; // 上一次渲染的 state(hooks 链表)
this.dependencies = null; // 依赖(context、事件等)
// ========== 工作模式与状态 ==========
this.mode = mode; // 渲染模式(并发模式等)
this.flags = NoFlags; // 副作用标记(原 effectTag)
this.subtreeFlags = NoFlags; // 子树副作用标记
this.deletions = null; // 需要删除的子节点
// ========== 优先级相关 ==========
this.lanes = NoLanes; // 该 Fiber 的优先级
this.childLanes = NoLanes; // 子树的优先级
// ========== 双缓冲机制 ==========
this.alternate = null; // 指向另一棵树的对应节点
}1.3.2 Fiber 树结构示意图
Fiber 树结构(单向链表树)
RootFiber
│
│ return
▼
App Fiber
/ \
child sibling
/ \
Div Fiber ──────► Span Fiber
/ \
child sibling
/ \
P Fiber ──────► Button Fiber ────► null
/ \
sibling child
/ \
Text Fiber "Click Me"
│
▼
null
关系说明:
- return: 指向父节点
- child: 指向第一个子节点
- sibling: 指向下一个兄弟节点1.3.3 双缓冲机制
Fiber 使用双缓冲机制来管理更新:
┌─────────────────────────────────────────────────────────────────┐
│ 双缓冲机制示意图 │
└─────────────────────────────────────────────────────────────────┘
Current 树(当前屏幕显示) WorkInProgress 树(正在构建)
┌──────────────────┐ ┌──────────────────┐
│ RootFiber │◄──alternate──│ RootFiber │
│ (current) │ │ (workInProgress) │
└────────┬─────────┘ └────────┬─────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ App Fiber │◄──alternate──│ App Fiber │
│ memoizedProps │ │ pendingProps │
│ memoizedState │ │ memoizedState │
└────────┬─────────┘ └────────┬─────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Div Fiber │◄──alternate──│ Div Fiber │
│ flags: NoFlags │ │ flags: Update │
└──────────────────┘ └──────────────────┘
工作流程:
1. 从 current 树克隆创建 workInProgress 树
2. 在 workInProgress 树上进行协调工作
3. 完成后,workInProgress 树变成新的 current 树
4. 原 current 树变成新的 workInProgress 树(复用)1.3.4 WorkTag 类型枚举
javascript
export const FunctionComponent = 0 // 函数组件
export const ClassComponent = 1 // 类组件
export const IndeterminateComponent = 2 // 初始渲染时不确定类型
export const HostRoot = 3 // 根节点(FiberRoot)
export const HostPortal = 4 // Portal
export const HostComponent = 5 // 原生 DOM 元素
export const HostText = 6 // 文本节点
export const Fragment = 7 // Fragment
export const Mode = 8 // 模式(StrictMode 等)
export const ContextConsumer = 9 // Context 消费者
export const ContextProvider = 10 // Context 提供者
export const ForwardRef = 11 // forwardRef
export const Profiler = 12 // Profiler
export const SuspenseComponent = 13 // Suspense
export const MemoComponent = 14 // React.memo
export const SimpleMemoComponent = 15 // 简单的 memo 组件
export const LazyComponent = 16 // React.lazy
export const OffscreenComponent = 22 // Offscreen(并发特性)1.3.5 FiberRoot 数据结构
javascript
function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) {
this.tag = tag // Root 类型
this.containerInfo = containerInfo // DOM 容器
this.pendingChildren = null // 子节点
this.current = null // 指向当前工作的 Fiber 树
// 更新相关
this.finishedWork = null // 已完成的 workInProgress 树
this.finishedLanes = NoLanes // 完成的优先级
// 优先级相关
this.pendingLanes = NoLanes // 待处理的优先级
this.suspendedLanes = NoLanes // 挂起的优先级
this.pingedLanes = NoLanes // 已触发的优先级
this.expiredLanes = NoLanes // 过期的优先级
// 回调相关
this.callbackNode = null // 调度回调
this.callbackPriority = NoLane // 回调优先级
// 其他
this.context = null // 上下文
this.pendingContext = null // 待处理的上下文
}┌─────────────────────────────────────────────────────────────────┐
│ FiberRoot 与 Fiber 树关系 │
└─────────────────────────────────────────────────────────────────┘
DOM 容器
┌─────────────────┐
│ <div id="root"> │
└────────┬────────┘
│ containerInfo
▼
┌─────────────────────┐
│ FiberRootNode │
│ - containerInfo │
│ - current ─────────┼──────┐
│ - pendingLanes │ │
│ - callbackNode │ │
└─────────────────────┘ │
│
▼
┌──────────────┐
│ HostRoot │
│ Fiber │
│ - stateNode ├───► FiberRootNode
│ - child │
└──────┬───────┘
│
▼
┌──────────────┐
│ App Fiber │
│ - return ├───► HostRoot
└──────────────┘2. 调和/提交完整工作流程
2.1 整体流程概览
React Fiber 的工作流程分为两个主要阶段:
┌─────────────────────────────────────────────────────────────────┐
│ React Fiber 工作流程总览 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ Render 阶段(可中断) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Reconcile(协调)阶段 │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ beginWork │──►│ completeWork │──►│ 标记副作用 │ │ │
│ │ │ (向下遍历) │ │ (向上回溯) │ │ (EffectTag) │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ │ 特点:可中断、可恢复、异步执行 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ Commit 阶段(不可中断) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Commit(提交)阶段 │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │beforeMutation│──►│ mutation │──►│afterMutation │ │ │
│ │ │ (读取状态) │ │ (操作DOM) │ │ (执行副作用) │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ │ 特点:不可中断、同步执行 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘2.2 详细工作流程图
┌─────────────────────────────────────────────────────────────────┐
│ React Fiber 详细工作流程 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────┐
│ 触发更新 │
│ setState/props │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 创建 Update │
│ 计算优先级 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 入队到 │
│ updateQueue │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 调度更新 │
│ ensureRootIsScheduled│
└────────┬────────┘
│
▼
┌────────────────────────────────────────┐
│ Render Phase(协调阶段) │
└────────────────────┬───────────────────┘
│
▼
┌─────────────────┐
│ prepareFreshStack│
│ 创建 workInProgress│
└────────┬────────┘
│
▼
┌────────────────────────────────────────┐
│ workLoopSync / workLoopConcurrent│
│ (工作循环,可中断) │
│ ┌─────────────────────────────────┐ │
│ │ while (workInProgress !== null) │ │
│ │ performUnitOfWork() │ │
│ │ 检查是否需要让出控制权 │ │
│ └─────────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ performUnitOfWork │
│ ┌─────────────────────────────────┐ │
│ │ 1. beginWork(workInProgress) │ │
│ │ - 处理当前节点 │ │
│ │ - 创建/复用子 Fiber │ │
│ │ - 返回子节点或 sibling │ │
│ │ │ │
│ │ 2. 如果没有子节点: │ │
│ │ completeWork(workInProgress)│ │
│ │ - 处理完成工作 │ │
│ │ - 创建 DOM 节点 │ │
│ │ - 冒泡副作用 │ │
│ │ - 返回 sibling 或 return │ │
│ └─────────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌─────────────────┐
│ 完成所有工作 │
│ finishedWork │
└────────┬────────┘
│
▼
┌────────────────────────────────────────┐
│ Commit Phase(提交阶段) │
│ 不可中断,同步执行 │
└────────────────────┬───────────────────┘
│
┌────────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│beforeMutation│ │ mutation │ │afterMutation │
│ 阶段 │ │ 阶段 │ │ 阶段 │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│commitBefore │ │commitMutation│ │commitLayout │
│MutationEffects│ │EffectsOnFiber│ │EffectsOnFiber│
│ │ │ │ │ │
│- 读取 DOM 状态│ │- 插入/更新/删除│ │- 执行生命周 │
│- 调用 │ │ DOM 节点 │ │ 期方法 │
│ getSnapshot │ │- 设置 DOM │ │- 调用 │
│ BeforeUpdate│ │ 属性 │ │ componentDidMount│
│ │ │- 处理 ref │ │ componentDidUpdate│
└──────────────┘ └──────────────┘ │- 执行 useLayout│
│ Effect 回调 │
│- 调度 useEffect│
└──────────────┘
│
▼
┌─────────────────┐
│ 切换 current │
│ 树指针 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 清理工作 │
│ 准备下一次更新 │
└─────────────────┘2.3 beginWork 详细解析
beginWork 是协调阶段的核心函数,负责处理每个 Fiber 节点:
┌─────────────────────────────────────────────────────────────────┐
│ beginWork 详细流程 │
└─────────────────────────────────────────────────────────────────┘
beginWork(current, workInProgress, renderLanes)
│
├──► 检查是否需要更新
│ │
│ ├── props 是否变化
│ ├── 优先级是否匹配
│ └── context 是否变化
│
├──► 如果不需要更新,返回 child(复用子节点)
│
└──► 需要更新,根据 tag 处理不同类型
│
├── FunctionComponent
│ └── updateFunctionComponent
│ ├── 渲染函数组件
│ ├── 处理 hooks
│ └── 返回子节点
│
├── ClassComponent
│ └── updateClassComponent
│ ├── 创建/复用实例
│ ├── 调用 render
│ └── 返回子节点
│
├── HostRoot
│ └── updateHostRoot
│ ├── 处理 updateQueue
│ └── 返回子节点
│
├── HostComponent (DOM 元素)
│ └── updateHostComponent
│ ├── 准备属性更新
│ └── 返回子节点
│
├── HostText
│ └── updateHostText
│ └── 处理文本内容
│
├── SuspenseComponent
│ └── updateSuspenseComponent
│ ├── 检查是否挂起
│ └── 显示 fallback 或内容
│
└── 其他类型...
beginWork 核心工作:
1. 比较 current 和 workInProgress
2. 决定是否可以复用(bailout)
3. 调用对应类型的更新函数
4. Diff 子节点(reconcileChildren)
5. 返回第一个子节点继续处理reconcileChildren 流程
┌─────────────────────────────────────────────────────────────────┐
│ reconcileChildren 详细流程 │
└─────────────────────────────────────────────────────────────────┘
reconcileChildren(current, workInProgress, nextChildren, renderLanes)
│
├──► 如果 current === null(首次渲染)
│ └── mountChildFibers
│ ├── 创建新的子 Fiber 节点
│ └── 不需要标记副作用(Placement)
│
└──► 如果 current !== null(更新渲染)
└── reconcileChildFibers
├── 标记副作用(Placement、Update、Deletion)
└── Diff 算法比较新旧子节点
Diff 算法(多节点比较):
┌─────────────────────────────────────────────────────────────────┐
│ 1. 单节点 Diff │
│ - 比较 key 和 type │
│ - 可复用:复用并标记更新 │
│ - 不可复用:创建新节点,标记删除旧节点 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 2. 多节点 Diff(两轮遍历) │
│ │
│ 第一轮遍历:处理更新的节点 │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ old: [A, B, C, D] │ │
│ │ new: [A, B, D, E] │ │
│ │ │ │
│ │ A → A (可复用,继续) │ │
│ │ B → B (可复用,继续) │ │
│ │ C → D (key 不同,停止第一轮) │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ 第二轮遍历:处理移动、新增、删除 │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 建立旧节点 key → index 映射 │ │
│ │ 遍历新节点,在映射中查找 │ │
│ │ - 找到:标记移动(Placement) │ │
│ │ - 未找到:标记新增(Placement) │ │
│ │ 旧节点中未匹配的:标记删除(Deletion) │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘2.4 completeWork 详细解析
completeWork 在遍历回溯时执行,处理叶子节点或已完成子树处理的节点:
┌─────────────────────────────────────────────────────────────────┐
│ completeWork 详细流程 │
└─────────────────────────────────────────────────────────────────┘
completeWork(current, workInProgress, renderLanes)
│
├──► 根据 tag 处理不同类型
│
├── HostComponent (DOM 元素)
│ │
│ ├── current === null(首次渲染)
│ │ ├── 创建 DOM 实例(createInstance)
│ │ ├── 设置 DOM 属性
│ │ ├── 插入子节点(appendAllChildren)
│ │ └── 设置 stateNode
│ │
│ └── current !== null(更新渲染)
│ ├── 比较 props 变化
│ └── 标记 Update 副作用
│
├── HostText
│ ├── 创建文本节点
│ └── 比较文本内容变化
│
├── FunctionComponent
│ └── 处理 context 等
│
├── ClassComponent
│ └── 处理 context 等
│
├── HostRoot
│ └── 冒泡处理
│
└── 其他类型...
completeWork 核心工作:
1. 创建/复用 DOM 节点
2. 收集 DOM 属性变更
3. 将子 DOM 节点插入当前 DOM 节点
4. 冒泡副作用标记(subtreeFlags)
5. 处理 ref副作用冒泡示意图
┌─────────────────────────────────────────────────────────────────┐
│ 副作用冒泡示意图 │
└─────────────────────────────────────────────────────────────────┘
completeWork 向上冒泡
RootFiber
│
│ subtreeFlags: Update | Placement
▼
App Fiber
│
│ subtreeFlags: Update
▼
Div Fiber (flags: Update)
│
│ subtreeFlags: Placement
▼
Span Fiber (flags: Placement)
│
▼
Text Fiber (flags: Update)
冒泡规则:
completeWork 时:
workInProgress.return.subtreeFlags |=
(workInProgress.flags | workInProgress.subtreeFlags)
这样在 Commit 阶段可以快速判断子树是否有副作用2.5 Commit 阶段详细流程
┌─────────────────────────────────────────────────────────────────┐
│ Commit 阶段详细流程 │
└─────────────────────────────────────────────────────────────────┘
commitRoot(root, finishedWork)
│
├──► 准备工作
│ ├── 获取优先级
│ ├── 准备 effect 链表
│ └── 清空相关状态
│
├──► 第一阶段:beforeMutation
│ │
│ └── commitBeforeMutationEffects
│ │
│ ├── 遍历 effect 链表
│ │
│ ├── ClassComponent
│ │ └── 调用 getSnapshotBeforeUpdate
│ │
│ ├── FunctionComponent
│ │ └── 调度 useEffect(异步)
│ │
│ └── HostRoot
│ └── 清空 pendingPassiveEffects
│
├──► 切换 current 树指针
│ root.current = finishedWork
│
├──► 第二阶段:mutation
│ │
│ └── commitMutationEffects
│ │
│ ├── 遍历 effect 链表(逆序处理删除)
│ │
│ ├── Placement(插入)
│ │ └── insertOrAppendPlacementNode
│ │ └── parent.appendChild(node)
│ │
│ ├── Update(更新)
│ │ └── commitWork
│ │ └── 更新 DOM 属性
│ │
│ ├── Deletion(删除)
│ │ └── commitDeletion
│ │ ├── 删除 DOM 节点
│ │ ├── 解绑 ref
│ │ └── 调用 componentWillUnmount
│ │
│ └── HostText
│ └── commitTextUpdate
│ └── node.nodeValue = newText
│
└──► 第三阶段:layout
│
└── commitLayoutEffects
│
├── ClassComponent
│ ├── componentDidMount
│ └── componentDidUpdate
│
├── FunctionComponent
│ └── 执行 useLayoutEffect 回调
│
├── HostComponent
│ └── 处理 ref
│
└── HostRoot
└── 处理 pendingCallbacks2.6 Effect 链表结构
┌─────────────────────────────────────────────────────────────────┐
│ Effect 链表结构 │
└─────────────────────────────────────────────────────────────────┘
在 completeWork 阶段,所有有副作用的 Fiber 节点被收集到一个链表中:
finishedWork.firstEffect ──► Fiber1 ──► Fiber2 ──► Fiber3 ──► null
│ │ │
▼ ▼ ▼
nextEffect nextEffect nextEffect
链表构建过程:
1. completeWork 时,将当前节点的 effect 链表合并到父节点
2. 如果当前节点有副作用,添加到父节点的 effect 链表末尾
3. 最终形成以 root.firstEffect 为头的单向链表
示例:
RootFiber
│
│ firstEffect
▼
Div Fiber ──────► Span Fiber ──────► null
(Update) (Placement)
▲
│
App Fiber
(无副作用)
Commit 阶段遍历这个链表执行副作用3. Fiber 与函数组件、Hooks 的关系
3.1 函数组件在 Fiber 中的处理
┌─────────────────────────────────────────────────────────────────┐
│ 函数组件 Fiber 处理流程 │
└─────────────────────────────────────────────────────────────────┘
beginWork(FunctionComponent)
│
└──► updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes)
│
├──► 准备 hooks 上下文
│ ├── currentlyRenderingFiber = workInProgress
│ ├── workInProgressHook = null
│ └── currentHook = current.memoizedState
│
├──► 执行函数组件
│ nextChildren = Component(nextProps, context)
│
├──► 处理 hooks
│ └── hooks 执行时会修改 workInProgress.memoizedState
│
├──► 重置 hooks 上下文
│
└──► reconcileChildren(处理子节点)
└── 返回 workInProgress.child3.2 Hooks 数据结构
javascript
const hook: Hook = {
memoizedState: null, // 当前 hook 的状态值
baseState: null, // 初始状态
baseQueue: null, // 待处理的更新队列
queue: null, // 更新队列
next: null, // 指向下一个 hook
};3.3 Fiber 与 Hooks 关系图
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 与 Hooks 关系图 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ FunctionComponent Fiber │
│ │
│ tag: FunctionComponent │
│ memoizedState ─────────────────────────────────────────────┐ │
│ │ │
│ ▼ │
│ ┌─────────────┐│
│ │ Hook 1 ││
│ │ (useState) ││
│ │ ││
│ │ memoizedState││
│ │ = 0 ││
│ │ queue ││
│ │ next ───────┼┼──┐
│ └─────────────┘│ │
│ │ │
│ ┌────────────────────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Hook 2 │ │
│ │ (useEffect) │ │
│ │ │ │
│ │ memoizedState│ │
│ │ = { │ │
│ │ tag, │ │
│ │ create, │ │
│ │ destroy,│ │
│ │ deps │ │
│ │ } │ │
│ │ next ───────┼───┐ │
│ └─────────────┘ │ │
│ │ │
│ ┌───────────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Hook 3 │ │
│ │ (useMemo) │ │
│ │ │ │
│ │ memoizedState│ │
│ │ = [ │ │
│ │ value, │ │
│ │ deps │ │
│ │ ] │ │
│ │ next ───────┼───► null │
│ └─────────────┘ │
│ │
│ updateQueue ──────────────────────────────────────────────────┐ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ UpdateQueue │ │
│ │ │ │
│ │ shared: { │ │
│ │ pending: Update1 ──► Update2 ──► Update3 ──► (循环回Update1)│ │
│ │ } │ │
│ │ │ │
│ │ effects: [ │ │
│ │ { tag, create, destroy, deps } // useEffect 定义 │ │
│ │ ] │ │
│ └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘3.4 Hooks 链表构建过程
┌─────────────────────────────────────────────────────────────────┐
│ Hooks 链表构建过程 │
└─────────────────────────────────────────────────────────────────┘
首次渲染(mount):
function Counter() {
const [count, setCount] = useState(0); // Hook 1
const [name, setName] = useState('React'); // Hook 2
useEffect(() => { // Hook 3
console.log('effect');
}, []);
return <div>{count}</div>;
}
执行过程:
┌─────────────────────────────────────────────────────────────────┐
│ 1. currentlyRenderingFiber = workInProgress │
│ 2. workInProgressHook = null │
│ 3. currentHook = null (首次渲染没有 current) │
└─────────────────────────────────────────────────────────────────┘
useState(0):
┌─────────────────────────────────────────────────────────────────┐
│ mountState(0) │
│ ├── 创建 Hook 对象 │
│ │ hook = { memoizedState: 0, baseState: 0, next: null } │
│ ├── 添加到链表 │
│ │ if (workInProgressHook === null) │
│ │ fiber.memoizedState = hook │
│ │ else │
│ │ workInProgressHook.next = hook │
│ └── workInProgressHook = hook │
└─────────────────────────────────────────────────────────────────┘
useState('React'):
┌─────────────────────────────────────────────────────────────────┐
│ mountState('React') │
│ ├── 创建 Hook 对象 │
│ │ hook = { memoizedState: 'React', next: null } │
│ └── workInProgressHook.next = hook │
│ workInProgressHook = hook │
└─────────────────────────────────────────────────────────────────┘
useEffect(...):
┌─────────────────────────────────────────────────────────────────┐
│ mountEffectImpl(...) │
│ ├── 创建 Hook 对象 │
│ │ hook = { memoizedState: effect, next: null } │
│ └── 添加到链表末尾 │
└─────────────────────────────────────────────────────────────────┘
最终链表结构:
fiber.memoizedState ──► Hook1 ──► Hook2 ──► Hook3 ──► null3.5 更新时的 Hooks 处理
┌─────────────────────────────────────────────────────────────────┐
│ 更新时 Hooks 处理流程 │
└─────────────────────────────────────────────────────────────────┘
更新渲染(update):
执行过程:
┌─────────────────────────────────────────────────────────────────┐
│ 1. currentlyRenderingFiber = workInProgress │
│ 2. workInProgressHook = null │
│ 3. currentHook = current.memoizedState (从 current 树获取) │
└─────────────────────────────────────────────────────────────────┘
useState 调用:
┌─────────────────────────────────────────────────────────────────┐
│ updateState(...) │
│ ├── 获取 currentHook │
│ │ currentHook = nextCurrentHook() │
│ │ │
│ ├── 复制 hook 到 workInProgress │
│ │ hook = { │
│ │ memoizedState: currentHook.memoizedState, │
│ │ baseState: currentHook.baseState, │
│ │ queue: currentHook.queue, │
│ │ next: null │
│ │ } │
│ │ │
│ ├── 处理更新队列 │
│ │ 遍历 hook.queue.pending,计算新 state │
│ │ │
│ ├── 更新 hook.memoizedState │
│ │ │
│ └── 添加到 workInProgress 的 hooks 链表 │
└─────────────────────────────────────────────────────────────────┘
Current 树与 WorkInProgress 树的 Hooks 关系:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ Current Fiber WorkInProgress Fiber │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ memoizedState │ │ memoizedState │ │
│ │ │ │ │ │ │ │
│ │ ▼ │ │ ▼ │ │
│ │ ┌─────────┐ │ clone │ ┌─────────┐ │ │
│ │ │ Hook 1 │────┼──────────────┼─►│ Hook 1 │ │ │
│ │ │ count:0│ │ │ │ count:1 │ │ │
│ │ └────┬────┘ │ │ └────┬────┘ │ │
│ │ │ │ │ │ │ │
│ │ ▼ │ │ ▼ │ │
│ │ ┌─────────┐ │ │ ┌─────────┐ │ │
│ │ │ Hook 2 │────┼──────────────┼─►│ Hook 2 │ │ │
│ │ │name:'A'│ │ │ │name:'B'│ │ │
│ │ └─────────┘ │ │ └─────────┘ │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘3.6 不同 Hooks 的 memoizedState 存储
┌─────────────────────────────────────────────────────────────────┐
│ 不同 Hooks 的 memoizedState 存储 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useState / useReducer │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ hook.memoizedState = stateValue │ │
│ │ hook.queue = { │ │
│ │ pending: Update { action, next } → Update → ... │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useEffect │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ hook.memoizedState = { │ │
│ │ tag: HookHasEffect | HookEffect, │ │
│ │ create: () => { ... }, // effect 回调 │ │
│ │ destroy: () => { ... }, // 清理函数 │ │
│ │ deps: [dep1, dep2], // 依赖数组 │ │
│ │ next: Effect ... // 链表 │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useLayoutEffect │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ 与 useEffect 类似,但 tag 不同 │ │
│ │ tag: HookHasEffect | HookLayout │ │
│ │ 在 mutation 阶段同步执行 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useRef │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ hook.memoizedState = { │ │
│ │ current: initialValue │ │
│ │ } │ │
│ │ // 返回 { current: ... } │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useMemo │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ hook.memoizedState = [ │ │
│ │ nextValue, // 计算后的值 │ │
│ │ nextDeps // 依赖数组 │ │
│ │ ] │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useCallback │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ hook.memoizedState = [ │ │
│ │ callback, // 函数引用 │ │
│ │ nextDeps // 依赖数组 │ │
│ │ ] │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ useContext │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ // 不使用 hook 链表存储 │ │
│ │ // 直接读取 context 的当前值 │ │
│ │ const context = readContext(Context); │ │
│ │ return context; │ │
│ │ │ │
│ │ // 但会在 fiber.dependencies 中添加依赖 │ │
│ │ fiber.dependencies = { │ │
│ │ firstContext: contextItem, │ │
│ │ lanes │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘3.7 Hooks 调用顺序的重要性
┌─────────────────────────────────────────────────────────────────┐
│ Hooks 调用顺序的重要性 │
└─────────────────────────────────────────────────────────────────┘
❌ 错误示例:条件调用 Hooks
┌─────────────────────────────────────────────────────────────────┐
│ function BadComponent({ isLoading }) { │
│ const [count, setCount] = useState(0); │
│ │
│ if (isLoading) { │
│ const [data, setData] = useState(null); // ❌ 条件调用 │
│ } │
│ │
│ const [name, setName] = useState(''); │
│ } │
│ │
│ 首次渲染 (isLoading = true): │
│ Hook1(count) → Hook2(data) → Hook3(name) │
│ │
│ 更新渲染 (isLoading = false): │
│ Hook1(count) → Hook3(name) // Hook2 被跳过! │
│ │
│ 结果:Hook 链表错乱,状态混乱 │
└─────────────────────────────────────────────────────────────────┘
✅ 正确示例:Hooks 必须在顶层调用
┌─────────────────────────────────────────────────────────────────┐
│ function GoodComponent({ isLoading }) { │
│ const [count, setCount] = useState(0); │
│ const [data, setData] = useState(null); // ✅ 始终调用 │
│ const [name, setName] = useState(''); │
│ │
│ // 在 Hook 之后使用条件判断 │
│ if (isLoading) { │
│ // 使用 data │
│ } │
│ } │
│ │
│ 每次渲染: │
│ Hook1(count) → Hook2(data) → Hook3(name) │
│ │
│ 结果:Hook 链表顺序一致,状态正确 │
└─────────────────────────────────────────────────────────────────┘
React 通过 hookIndex 确保调用顺序:
┌─────────────────────────────────────────────────────────────────┐
│ let hookIndex = 0; │
│ │
│ function useState(initialState) { │
│ const hook = currentHook || createNewHook(); │
│ if (hookIndex !== expectedIndex) { │
│ throw new Error('Hooks order changed!'); │
│ } │
│ hookIndex++; │
│ return [hook.memoizedState, dispatch]; │
│ } │
└─────────────────────────────────────────────────────────────────┘4. Fiber 的中断恢复与优先级调度
4.1 Scheduler 调度器
┌─────────────────────────────────────────────────────────────────┐
│ Scheduler 调度器架构 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ Scheduler │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 任务队列(优先队列) │ │
│ │ │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ Task 1 │──►│ Task 2 │──►│ Task 3 │──►│ Task 4 │ │ │
│ │ │Priority│ │Priority│ │Priority│ │Priority│ │ │
│ │ │ 1 │ │ 2 │ │ 3 │ │ 5 │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ │ (高优先级) (中优先级) (低优先级) (最低优先级) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 调度方法 │ │
│ │ │ │
│ │ - scheduleCallback(priority, callback) │ │
│ │ - cancelCallback(task) │ │
│ │ - getFirstCallbackNode() │ │
│ │ - shouldYield() │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 时间切片控制 │ │
│ │ │ │
│ │ - yieldInterval = 5ms (默认) │ │
│ │ - deadline = currentTime + yieldInterval │ │
│ │ - shouldYield() = currentTime >= deadline │ │
│ └─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘4.2 优先级系统
┌─────────────────────────────────────────────────────────────────┐
│ React 优先级系统 │
└─────────────────────────────────────────────────────────────────┘
Lane(车道)模型(React 18+):
┌──────────────────────────────────────────────────────────────────┐
│ export const TotalLanes = 31; │
│ │
│ // 同步优先级(最高) │
│ export const SyncLane: Lane = 0b0000000000000000000000000000001;│
│ │
│ // 连续触发优先级 │
│ export const InputContinuousHydrationLane: Lane = │
│ 0b0000000000000000000000000000010; │
│ export const InputContinuousLane: Lane = │
│ 0b0000000000000000000000000000100; │
│ │
│ // 默认优先级 │
│ export const DefaultLane: Lane = │
│ 0b0000000000000000000000000001000; │
│ │
│ // 过渡优先级 │
│ export const TransitionLanes: Lanes = │
│ 0b0000000001111111111111110000000; │
│ │
│ // 空闲优先级(最低) │
│ export const IdleLane: Lane = │
│ 0b0100000000000000000000000000000; │
└──────────────────────────────────────────────────────────────────┘
优先级从高到低:
┌──────────────────────────────────────────────────────────────────┐
│ 1. SyncLane - 同步(用户输入、离散事件) │
│ 2. InputContinuousLane - 连续输入(拖拽、滚动) │
│ 3. DefaultLane - 默认(普通更新) │
│ 4. TransitionLane - 过渡(useTransition) │
│ 5. IdleLane - 空闲(后台任务) │
└──────────────────────────────────────────────────────────────────┘
优先级示意图:
高优先级 ◄──────────────────────────────────► 低优先级
SyncLane InputContinuous Default Transition Idle
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
│ 1 │ │ 2-4 │ │ 8 │ │ 128+ │ │ 2^30 │
│ 用户 │ │ 连续 │ │ 普通 │ │ 过渡 │ │ 空闲 │
│ 输入 │ │ 输入 │ │ 更新 │ │ 更新 │ │ 任务 │
└───────┘ └───────┘ └───────┘ └───────┘ └───────┘4.3 时间切片与中断机制
┌─────────────────────────────────────────────────────────────────┐
│ 时间切片与中断机制 │
└─────────────────────────────────────────────────────────────────┘
工作循环(workLoopConcurrent):
┌──────────────────────────────────────────────────────────────────┐
│ function workLoopConcurrent() { │
│ while (workInProgress !== null && !shouldYield()) { │
│ performUnitOfWork(workInProgress); │
│ } │
│ } │
│ │
│ function shouldYield() { │
│ // 检查是否超过时间切片 │
│ // 检查是否有更高优先级任务 │
│ return currentTime >= deadline || hasHigherPriorityWork(); │
│ } │
└──────────────────────────────────────────────────────────────────┘
时间切片工作原理图:
┌──────────────────────────────────────────────────────────────────┐
│ 时间切片示意图 │
│ │
│ 时间线 ──────────────────────────────────────────────────────► │
│ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 一帧(约 16.6ms) ││
│ │ ┌─────────┬─────────┬─────────┬─────────┬─────────┐ ││
│ │ │ 用户 │ 样式 │ 布局 │ 绘制 │ 合成 │ ││
│ │ │ 交互 │ 计算 │ 计算 │ │ │ ││
│ │ └─────────┴─────────┴─────────┴─────────┴─────────┘ ││
│ │ ││
│ │ React 利用空闲时间执行任务: ││
│ │ ┌──────────────────────────────────────────────────────┐ ││
│ │ │ React 任务 │ ││
│ │ │ ┌───────┬───────┬───────┬───────┬───────┐ │ ││
│ │ │ │ Task1 │ Task2 │ Task3 │ Task4 │ Task5 │ │ ││
│ │ │ │ 1ms │ 1ms │ 1ms │ 1ms │ 1ms │ │ ││
│ │ │ └───────┴───────┴───────┴───────┴───────┘ │ ││
│ │ │ │ ││
│ │ │ 每个 Task 后检查 shouldYield() │ ││
│ │ │ 如果需要让出控制权,保存当前状态,等待下次继续 │ ││
│ │ └──────────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────┘
中断与恢复流程:
┌──────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ │
│ │ 开始渲染任务 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 执行 Fiber 工作 ││
│ │ ││
│ │ workInProgress ──► Fiber1 ──► Fiber2 ──► Fiber3 ──► ... ││
│ │ ││
│ │ 每个 Fiber 处理后: ││
│ │ if (shouldYield()) { ││
│ │ // 中断,保存状态 ││
│ │ return; ││
│ │ } ││
│ └──────────────────────────┬──────────────────────────────────┘│
│ │ │
│ ┌───────────────────┴───────────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ shouldYield │ │ 完成工作 │ │
│ │ = true │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 保存当前状态: │ │ 进入 Commit │ │
│ │ - workInProgress │ │ 阶段 │ │
│ │ - nextUnitOfWork │ └─────────────────┘ │
│ └──────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 让出控制权给浏览器│ │
│ │ scheduler.postTask│ │
│ │ 或 MessageChannel│ │
│ └──────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 浏览器执行其他任务│ │
│ │ (渲染、交互等) │ │
│ └──────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 下一个时间切片 │ │
│ │ 恢复中断的任务 │ │
│ └──────┬──────────┘ │
│ │ │
│ └───────────────────────────────────────────────────────│
│ │ │
│ ▼ │
│ 继续处理 Fiber 工作 │
│ │
└──────────────────────────────────────────────────────────────────┘4.4 高优先级任务打断低优先级任务
┌─────────────────────────────────────────────────────────────────┐
│ 高优先级打断低优先级流程 │
└─────────────────────────────────────────────────────────────────┘
场景:低优先级更新正在执行,用户触发高优先级输入
时间线:
┌──────────────────────────────────────────────────────────────────┐
│ │
│ T1: 开始低优先级更新(DefaultLane) │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ workInProgress: Fiber1 → Fiber2 → Fiber3 (进行中) ││
│ │ ││
│ │ Fiber 树状态: ││
│ │ Root ││
│ │ │ ││
│ │ ▼ ││
│ │ App (已处理) ││
│ │ │ ││
│ │ ▼ ││
│ │ Div (已处理) ││
│ │ │ ││
│ │ ▼ ││
│ │ List (处理中) ◄─── workInProgress 指针 ││
│ │ │ ││
│ │ ▼ ││
│ │ Item (未处理) ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ T2: 用户点击,触发高优先级更新(SyncLane) │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 检测到更高优先级任务 ││
│ │ shouldYield() = true ││
│ │ ││
│ │ 保存当前状态: ││
│ │ - 保存 workInProgress 树 ││
│ │ - 记录中断位置 ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ T3: 处理高优先级更新 │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 从 Root 开始新的渲染 ││
│ │ ││
│ │ Fiber 树状态: ││
│ │ Root ││
│ │ │ ││
│ │ ▼ ││
│ │ App ││
│ │ │ ││
│ │ ▼ ││
│ │ Button (高优先级更新) ││
│ │ ││
│ │ 快速完成并提交 ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ T4: 恢复低优先级更新 │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 从保存的位置继续 ││
│ │ 但需要重新开始(因为状态可能已变化) ││
│ │ ││
│ │ 或者:复用之前的工作(如果适用) ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
└──────────────────────────────────────────────────────────────────┘
优先级打断机制:
┌──────────────────────────────────────────────────────────────────┐
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 任务队列状态 │ │
│ │ │ │
│ │ 执行前: │ │
│ │ ┌────────┐ │ │
│ │ │ Task A │ (DefaultLane, 低优先级) │ │
│ │ └────────┘ │ │
│ │ │ │
│ │ 高优先级任务进入: │ │
│ │ ┌────────┐ ┌────────┐ │ │
│ │ │ Task B │──►│ Task A │ │ │
│ │ │(Sync) │ │(Default)│ │ │
│ │ └────────┘ └────────┘ │ │
│ │ │ │
│ │ Task B 插队到前面,优先执行 │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ 检查是否需要打断: │
│ function checkForInterruption() { │
│ const nextLane = getNextLane(root); │
│ if (nextLane > currentLane) { │
│ // 有更高优先级任务,需要中断 │
│ return true; │
│ } │
│ return false; │
│ } │
│ │
└──────────────────────────────────────────────────────────────────┘4.5 控制权交还浏览器机制
┌─────────────────────────────────────────────────────────────────┐
│ 控制权交还浏览器机制 │
└─────────────────────────────────────────────────────────────────┘
React 使用多种机制让出控制权:
1. MessageChannel(主要方式)
┌──────────────────────────────────────────────────────────────────┐
│ const channel = new MessageChannel(); │
│ const port = channel.port2; │
│ channel.port1.onmessage = performWorkUntilDeadline; │
│ │
│ function schedulePerformWorkUntilDeadline() { │
│ port.postMessage(null); // 发送消息 │
│ } │
│ │
│ function performWorkUntilDeadline() { │
│ // 在下一个事件循环中执行 │
│ // 浏览器有机会处理其他任务 │
│ } │
│ │
│ 工作流程: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ React 执行任务 │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ shouldYield() = true │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ port.postMessage(null) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────┐│ │
│ │ │ 浏览器事件循环 ││ │
│ │ │ - 处理用户交互 ││ │
│ │ │ - 执行渲染 ││ │
│ │ │ - 处理其他任务 ││ │
│ │ └─────────────────────────────────────────────────────────┘│ │
│ │ │ │ │
│ │ ▼ │ │
│ │ MessageChannel 回调触发 │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ 继续执行 React 任务 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
2. requestAnimationFrame(用于动画)
┌──────────────────────────────────────────────────────────────────┐
│ function scheduleAnimationCallback(callback) { │
│ requestAnimationFrame((timestamp) => { │
│ callback(timestamp); │
│ }); │
│ } │
│ │
│ 在下一帧执行,适合动画相关任务 │
└──────────────────────────────────────────────────────────────────┘
3. Scheduler API(现代浏览器)
┌──────────────────────────────────────────────────────────────────┐
│ if (typeof scheduler !== 'undefined' && scheduler.postTask) { │
│ scheduler.postTask(callback, { │
│ priority: 'user-blocking' // 或 'user-visible', 'background'│
│ }); │
│ } │
│ │
│ 浏览器原生调度 API,更精确的优先级控制
└──────────────────────────────────────────────────────────────────┘5. Fiber 数据视图更新渲染流程
5.1 整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ React Fiber 整体架构图 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ 用户层(User Layer) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ JSX → React.createElement() → React Elements │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ React 层(React Layer) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ React DOM / React Native │ │
│ │ - createRoot() / render() │ │
│ │ - 状态管理(useState, useReducer) │ │
│ │ - 副作用管理(useEffect, useLayoutEffect) │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ 调度层(Scheduler Layer) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Scheduler │ │
│ │ - 任务优先级调度 │ │
│ │ - 时间切片管理 │ │
│ │ - 任务中断与恢复 │ │
│ │ - 控制权交还浏览器 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ 协调层(Reconciler Layer) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ React Fiber Reconciler │ │
│ │ - Fiber 树构建 │ │
│ │ - Diff 算法 │ │
│ │ - 副作用标记 │ │
│ │ - 双缓冲机制 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ 渲染层(Renderer Layer) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ DOM Renderer / Native Renderer │ │
│ │ - DOM 节点操作 │ │
│ │ - 属性更新 │ │
│ │ - 事件处理 │ │
│ │ - 样式应用 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ 宿主环境(Host Environment) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Browser DOM / iOS / Android / Canvas │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘5.2 数据流与更新流程
┌─────────────────────────────────────────────────────────────────┐
│ 数据流与更新流程图 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────┐
│ 用户操作 │
│ 点击/输入等 │
└────────┬────────┘
│
▼
┌────────────────────────────────────────┐
│ 触发状态更新 │
│ - setState / dispatch │
│ - props 变化 │
│ - context 变化 │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 创建 Update 对象 │
│ ┌──────────────────────────────────┐ │
│ │ const update = { │ │
│ │ lane: priority, │ │
│ │ action: action, │ │
│ │ eagerReducer: null, │ │
│ │ eagerState: null, │ │
│ │ next: null │ │
│ │ } │ │
│ └──────────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 入队到 updateQueue │
│ ┌──────────────────────────────────┐ │
│ │ fiber.updateQueue.shared.pending │ │
│ │ ┌─────────┐ │ │
│ │ │ Update1 │ │ │
│ │ └────┬────┘ │ │
│ │ │ │ │
│ │ ┌────▼────┐ │ │
│ │ │ Update2 │ │ │
│ │ └────┬────┘ │ │
│ │ │ │ │
│ │ ┌────▼────┐ │ │
│ │ │ Update3 │──► 循环回 Update1│ │
│ │ └─────────┘ │ │
│ └──────────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 调度更新 │
│ ensureRootIsScheduled(root) │
│ - 获取最高优先级 lane │
│ - 创建调度回调 │
│ - scheduleCallback(priority, callback)│
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 协调阶段(Render Phase) │
│ - 可中断 │
│ - 构建 workInProgress 树 │
│ - 计算 state │
│ - Diff 子节点 │
│ - 标记副作用 │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 提交阶段(Commit Phase) │
│ - 不可中断 │
│ - beforeMutation │
│ - mutation │
│ - layout │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ DOM 更新 │
│ - 插入/更新/删除节点 │
│ - 更新属性 │
│ - 更新文本内容 │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 浏览器渲染 │
│ - 样式计算 │
│ - 布局计算 │
│ - 绘制 │
│ - 合成 │
└────────────────────┬───────────────────┘
│
▼
┌─────────────────┐
│ 用户看到更新 │
└─────────────────┘5.3 State 计算流程
┌─────────────────────────────────────────────────────────────────┐
│ State 计算流程 │
└─────────────────────────────────────────────────────────────────┘
在 beginWork 阶段处理 updateQueue:
processUpdateQueue(workInProgress, props, instance, renderLanes)
│
├──► 获取 updateQueue
│ queue = workInProgress.updateQueue
│
├──► 获取 pending updates
│ pendingQueue = queue.shared.pending
│
├──► 遍历更新队列
│ ┌────────────────────────────────────────────────────┐
│ │ let newState = queue.baseState; │
│ │ │
│ │ // 遍历环形链表 │
│ │ let update = pendingQueue; │
│ │ do { │
│ │ // 检查优先级 │
│ │ if (isSubsetOfLanes(update.lane, renderLanes)) {│
│ │ // 优先级匹配,计算新 state │
│ │ newState = getStateFromUpdate( │
│ │ workInProgress, │
│ │ queue, │
│ │ update, │
│ │ newState, │
│ │ props, │
│ │ instance │
│ │ ); │
│ │ } else { │
│ │ // 优先级不匹配,跳过 │
│ │ // 加入到 baseQueue │
│ │ } │
│ │ update = update.next; │
│ │ } while (update !== pendingQueue); │
│ └────────────────────────────────────────────────────┘
│
└──► 更新 state
workInProgress.memoizedState = newState
State 计算示例:
┌──────────────────────────────────────────────────────────────────┐
│ // 初始 state = 0 │
│ // 点击按钮 3 次,触发 3 个 setState │
│ │
│ setState(1) → Update1 { action: 1, lane: Default } │
│ setState(prev => prev + 1) → Update2 { action: fn, lane: Default}│
│ setState(3) → Update3 { action: 3, lane: Default } │
│ │
│ 计算过程: │
│ baseState = 0 │
│ Update1: newState = 1 │
│ Update2: newState = 1 + 1 = 2 │
│ Update3: newState = 3 (覆盖) │
│ │
│ 最终 state = 3 │
└──────────────────────────────────────────────────────────────────┘5.4 完整渲染流程示意图
┌─────────────────────────────────────────────────────────────────┐
│ 完整渲染流程示意图 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────┐
│ React 应用的 │
│ 初始化渲染 │
└────────┬────────┘
│
▼
┌────────────────────────────────────────┐
│ createRoot(container) │
│ 或 render(<App />, container) │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 创建 FiberRoot 和 HostRoot Fiber │
│ ┌──────────────────────────────┐ │
│ │ FiberRootNode │ │
│ │ - containerInfo: container │ │
│ │ - current: HostRoot Fiber │ │
│ └──────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 创建初始化 Update │
│ ┌──────────────────────────────┐ │
│ │ const update = { │ │
│ │ element: <App />, │ │
│ │ lane: SyncLane │ │
│ │ } │ │
│ └──────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 调度初始化渲染 │
│ scheduleUpdateOnFiber(root) │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Render Phase(协调阶段) │
│ ┌──────────────────────────────┐ │
│ │ 1. prepareFreshStack() │ │
│ │ 创建 workInProgress 树 │ │
│ │ │ │
│ │ 2. workLoopSync() │ │
│ │ while (workInProgress) { │ │
│ │ performUnitOfWork() │ │
│ │ } │ │
│ │ │ │
│ │ 3. beginWork() │ │
│ │ - 创建 Fiber 节点 │ │
│ │ - Diff 子节点 │ │
│ │ │ │
│ │ 4. completeWork() │ │
│ │ - 创建 DOM 节点 │ │
│ │ - 收集副作用 │ │
│ └──────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Commit Phase(提交阶段) │
│ ┌──────────────────────────────┐ │
│ │ 1. beforeMutation │ │
│ │ - 调度 useEffect │ │
│ │ │ │
│ │ 2. mutation │ │
│ │ - 插入 DOM 节点 │ │
│ │ - 设置 DOM 属性 │ │
│ │ │ │
│ │ 3. layout │ │
│ │ - 执行 useLayoutEffect │ │
│ │ - 调用 componentDidMount │ │
│ │ - 处理 ref │ │
│ └──────────────────────────────┘ │
└────────────────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 切换 current 指针 │
│ root.current = finishedWork │
└────────────────────┬───────────────────┘
│
▼
┌─────────────────┐
│ 渲染完成 │
│ 用户看到 UI │
└─────────────────┘6. Fiber 与 Stack Reconcile 协调算法
6.1 核心区别对比表
┌─────────────────────────────────────────────────────────────────┐
│ Fiber vs Stack Reconciler 对比 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────┬─────────────────────┬─────────────────────────────┐
│ 特性 │ Stack Reconciler │ Fiber Reconciler │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 更新方式 │ 同步不可中断递归更新 │ 异步可中断可恢复更新 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 数据结构 │ 虚拟 DOM 树 │ Fiber 树(链表) │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 优先级调度 │ 无优先级概念 │ 基于优先级的调度 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 时间切片 │ 不支持 │ 支持 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 用户交互响应 │ 可能卡顿 │ 流畅响应 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 任务分配 │ 一次性完成 │ 分片执行 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 控制权 │ 一直持有 │ 可交还给浏览器 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 渲染阶段 │ 单一阶段 │ Render + Commit 两阶段 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 副作用处理 │ 立即执行 │ 收集后统一执行 │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 错误边界 │ 不支持 │ 支持(componentDidCatch) │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ 并发特性 │ 不支持 │ 支持(React 18+) │
├──────────────┼─────────────────────┼─────────────────────────────┤
│ Suspense │ 不支持 │ 支持 │
└──────────────┴─────────────────────┴─────────────────────────────┘6.2 Stack Reconciler 工作原理
┌─────────────────────────────────────────────────────────────────┐
│ Stack Reconciler 工作原理 │
└─────────────────────────────────────────────────────────────────┘
递归遍历虚拟 DOM 树:
function mountComponent(element) {
if (typeof element.type === 'function') {
// 函数组件或类组件
const component = new element.type(element.props);
const renderedElement = component.render();
return mountComponent(renderedElement);
} else if (typeof element.type === 'string') {
// DOM 元素
const dom = document.createElement(element.type);
// 设置属性
Object.keys(element.props).forEach(key => {
if (key !== 'children') {
dom[key] = element.props[key];
}
});
// 递归处理子节点
element.props.children.forEach(child => {
const childDom = mountComponent(child);
dom.appendChild(childDom);
});
return dom;
}
}
问题:
┌──────────────────────────────────────────────────────────────────┐
│ 1. 递归调用栈过深 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ mountComponent │ │
│ │ └── mountComponent │ │
│ │ └── mountComponent │ │
│ │ └── mountComponent │ │
│ │ └── mountComponent │ │
│ │ └── ... (调用栈溢出风险) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 2. 无法中断 │
│ - 一旦开始渲染,必须完成所有工作 │
│ - 用户交互被阻塞 │
│ - 动画卡顿 │
│ │
│ 3. 无优先级 │
│ - 所有更新同等重要 │
│ - 用户输入和后台更新无法区分 │
│ │
│ 4. 性能问题 │
│ - 大型应用更新慢 │
│ - 主线程长时间阻塞 │
└──────────────────────────────────────────────────────────────────┘6.3 Fiber 的改进
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 的改进 │
└─────────────────────────────────────────────────────────────────┘
1. 链表结构替代递归
┌──────────────────────────────────────────────────────────────────┐
│ Fiber 树使用链表结构: │
│ │
│ - return: 父节点 │
│ - child: 第一个子节点 │
│ - sibling: 下一个兄弟节点 │
│ │
│ 遍历方式: │
│ function workLoop() { │
│ while (workInProgress !== null) { │
│ workInProgress = performUnitOfWork(workInProgress); │
│ if (shouldYield()) { │
│ // 可以中断 │
│ return; │
│ } │
│ } │
│ } │
│ │
│ 优势: │
│ - 不使用递归调用栈 │
│ - 可以随时暂停和恢复 │
│ - 调用栈深度可控 │
└──────────────────────────────────────────────────────────────────┘
2. 优先级调度
┌──────────────────────────────────────────────────────────────────┐
│ 不同类型的更新有不同的优先级: │
│ │
│ 高优先级: │
│ - 用户输入(键盘、鼠标点击) │
│ - 悬停、焦点 │
│ │
│ 中优先级: │
│ - 数据获取完成 │
│ - 普通状态更新 │
│ │
│ 低优先级: │
│ - 分析数据 │
│ - 预加载内容 │
│ │
│ 效果: │
│ - 用户交互始终流畅 │
│ - 后台任务不影响用户体验 │
└──────────────────────────────────────────────────────────────────┘
3. 时间切片
┌──────────────────────────────────────────────────────────────────┐
│ 将大任务拆分成小任务单元: │
│ │
│ Stack Reconciler: │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ████████████████████████████████████████████████████ ││
│ │ │←─────────────── 长时间阻塞(500ms)─────────────────→│ ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ Fiber: │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ││
│ │ │←5ms→│让出│←5ms→│让出│←5ms→│让出│←5ms→│让出│... ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ 效果: │
│ - 浏览器有机会处理用户交互 │
│ - 动画流畅 │
│ - 页面响应迅速 │
└──────────────────────────────────────────────────────────────────┘
4. 双缓冲机制
┌──────────────────────────────────────────────────────────────────┐
│ 内存中维护两棵树: │
│ │
│ Current 树:当前显示的内容 │
│ WorkInProgress 树:正在构建的内容 │
│ │
│ 优势: │
│ - 更新过程不阻塞显示 │
│ - 可以中断和恢复 │
│ - 用户看到的是完整的内容 │
└──────────────────────────────────────────────────────────────────┘6.4 性能对比示意图
┌─────────────────────────────────────────────────────────────────┐
│ 性能对比示意图 │
└─────────────────────────────────────────────────────────────────┘
场景:大型列表更新 + 用户输入
Stack Reconciler:
┌──────────────────────────────────────────────────────────────────┐
│ 时间线 ──────────────────────────────────────────────────────► │
│ │
│ 用户点击 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ████████████████████████████████████████████████████████ ││
│ │ │←─────────── 列表更新(阻塞 500ms)─────────────────→│ ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ 用户输入(键盘) │
│ │ │
│ ▼ (无响应,等待更新完成) │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ││
│ │ │←─────────── 继续阻塞 ───────────────────────────→│ ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ 结果:用户感觉卡顿,输入延迟 │
└──────────────────────────────────────────────────────────────────┘
Fiber Reconciler:
┌──────────────────────────────────────────────────────────────────┐
│ 时间线 ──────────────────────────────────────────────────────► │
│ │
│ 用户点击 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ││
│ │ │←列表更新(分片)→│让出│←继续→│让出│←继续→│让出│... ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ 用户输入(键盘) │
│ │ │
│ ▼ (立即响应) │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ▓▓▓▓▓▓ ││
│ │ │←高优先级更新(立即执行)→│ ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ 继续列表更新 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ││
│ │ │←继续分片执行→│让出│←继续→│让出│←继续→│... ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ 结果:用户交互流畅,输入即时响应 │
└──────────────────────────────────────────────────────────────────┘7. Fiber 全面总结
7.1 核心要点总结
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 核心要点总结 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ 1. Fiber 是什么? │
│ - React 16 引入的新协调算法 │
│ - 一种数据结构,代表工作单元 │
│ - 支持增量渲染的核心机制 │
├──────────────────────────────────────────────────────────────────┤
│ 2. 核心特性 │
│ ✓ 可中断:任务可以被暂停 │
│ ✓ 可恢复:任务可以从中断点继续 │
│ ✓ 优先级调度:高优先级任务可以打断低优先级任务 │
│ ✓ 时间切片:将大任务拆分成小任务单元 │
│ ✓ 双缓冲:内存中维护两棵 Fiber 树 │
├──────────────────────────────────────────────────────────────────┤
│ 3. 工作流程 │
│ Render Phase(可中断) │
│ ├── beginWork:向下遍历,处理节点 │
│ └── completeWork:向上回溯,收集副作用 │
│ │
│ Commit Phase(不可中断) │
│ ├── beforeMutation:读取 DOM 状态 │
│ ├── mutation:操作 DOM │
│ └── layout:执行副作用 │
├──────────────────────────────────────────────────────────────────┤
│ 4. 数据结构 │
│ Fiber 节点: │
│ - return / child / sibling:树结构 │
│ - memoizedState:状态(hooks 链表) │
│ - flags:副作用标记 │
│ - lanes:优先级 │
│ - alternate:双缓冲 │
├──────────────────────────────────────────────────────────────────┤
│ 5. Hooks 集成 │
│ - Hooks 存储在 Fiber.memoizedState 链表中 │
│ - 调用顺序必须一致 │
│ - 不同 Hook 有不同的 memoizedState 结构 │
├──────────────────────────────────────────────────────────────────┤
│ 6. 优先级系统 │
│ Lane 模型: │
│ - SyncLane:最高优先级(用户输入) │
│ - InputContinuousLane:连续输入 │
│ - DefaultLane:默认优先级 │
│ - TransitionLane:过渡更新 │
│ - IdleLane:最低优先级(后台任务) │
└──────────────────────────────────────────────────────────────────┘7.2 Fiber 架构总览图
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 架构总览图 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────┐
│ React 应用 │
└──────────┬──────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Scheduler │ │ Reconciler │ │ Renderer │
│ 调度器 │ │ 协调器 │ │ 渲染器 │
├───────────────┤ ├───────────────┤ ├───────────────┤
│ - 任务队列 │ │ - Fiber 树 │ │ - DOM 操作 │
│ - 优先级排序 │ │ - Diff 算法 │ │ - 事件处理 │
│ - 时间切片 │ │ - 副作用标记 │ │ - 属性更新 │
│ - 中断恢复 │ │ - 双缓冲 │ │ - 样式应用 │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
│ │ │
└──────────────────────┼──────────────────────┘
│
▼
┌─────────────────────┐
│ Fiber 核心概念 │
├─────────────────────┤
│ • Fiber 节点 │
│ • Fiber 树 │
│ • 双缓冲机制 │
│ • 优先级调度 │
│ • 时间切片 │
│ • 副作用链表 │
│ • Hooks 链表 │
│ • Update 队列 │
└─────────────────────┘7.3 Fiber 的优势
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 的优势 │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ 1. 用户体验提升 │
│ ✓ 高优先级任务优先处理(用户输入即时响应) │
│ ✓ 动画流畅(不阻塞渲染) │
│ ✓ 交互响应迅速 │
│ ✓ 避免页面卡顿 │
├──────────────────────────────────────────────────────────────────┤
│ 2. 性能优化 │
│ ✓ 增量渲染(分片执行) │
│ ✓ 任务复用(中断后可恢复) │
│ ✓ 批量更新(合并多个更新) │
│ ✓ 避免不必要的渲染(bailout) │
├──────────────────────────────────────────────────────────────────┤
│ 3. 新特性支持 │
│ ✓ Suspense(异步渲染) │
│ ✓ Concurrent Mode(并发模式) │
│ ✓ Transitions(过渡更新) │
│ ✓ Server Components(服务端组件) │
│ ✓ Offscreen(离屏渲染) │
├──────────────────────────────────────────────────────────────────┤
│ 4. 开发体验 │
│ ✓ 更好的错误处理(错误边界) │
│ ✓ 更清晰的更新流程 │
│ ✓ 更好的调试支持 │
│ ✓ Hooks 支持 │
├──────────────────────────────────────────────────────────────────┤
│ 5. 架构优势 │
│ ✓ 模块化设计 │
│ ✓ 跨平台支持(DOM、Native、Canvas 等) │
│ ✓ 可扩展性强 │
│ ✓ 代码可维护性高 │
└──────────────────────────────────────────────────────────────────┘7.4 Fiber 的应用场景
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 的应用场景 │
└─────────────────────────────────────────────────────────────────┘
1. 大型列表渲染
- 虚拟列表
- 无限滚动
- 分片加载
2. 复杂表单
- 实时验证
- 动态字段
- 大量输入
3. 动画和交互
- 拖拽
- 手势
- 过渡动画
4. 数据可视化
- 大量图表
- 实时更新
- 复杂渲染
5. 实时应用
- 聊天应用
- 协作编辑
- 实时数据流
6. 游戏和模拟
- Canvas 渲染
- 物理模拟
- 实时状态7.5 最佳实践
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 最佳实践 │
└─────────────────────────────────────────────────────────────────┘
1. 合理使用优先级
- 使用 useTransition 标记低优先级更新
- 使用 useDeferredValue 延迟非关键更新
- 避免在高优先级更新中执行耗时操作
2. 优化渲染性能
- 使用 React.memo 避免不必要的重新渲染
- 使用 useMemo 和 useCallback 缓存计算结果
- 合理拆分组件,减少更新范围
3. 正确使用 Hooks
- 保持 Hooks 调用顺序一致
- 在顶层调用 Hooks,不要在条件语句中调用
- 正确设置依赖数组
4. 避免阻塞主线程
- 将大型计算拆分成小任务
- 使用 Web Worker 处理耗时计算
- 利用 requestIdleCallback 处理低优先级任务
5. 合理使用 Suspense
- 配合 React.lazy 实现代码分割
- 使用 Suspense 处理数据加载
- 提供合适的 fallback UI
6. 监控和调试
- 使用 React DevTools 分析渲染性能
- 使用 Profiler 识别性能瓶颈
- 监控关键性能指标7.6 总结
┌─────────────────────────────────────────────────────────────────┐
│ Fiber 总结 │
└─────────────────────────────────────────────────────────────────┘
React Fiber 是 React 架构的一次重大升级,它通过以下核心机制
实现了增量渲染和优先级调度:
┌──────────────────────────────────────────────────────────────────┐
│ 核心机制 │
├──────────────────────────────────────────────────────────────────┤
│ 1. Fiber 数据结构 │
│ - 链表树结构,支持中断和恢复 │
│ - 包含组件信息、状态、副作用等 │
│ │
│ 2. 双缓冲机制 │
│ - Current 树和 WorkInProgress 树 │
│ - 无中断更新,平滑切换 │
│ │
│ 3. 优先级调度 │
│ - Lane 模型,31 位优先级 │
│ - 高优先级任务可以打断低优先级任务 │
│ │
│ 4. 时间切片 │
│ - 将大任务拆分成小任务单元 │
│ - 定期让出控制权给浏览器 │
│ │
│ 5. 两阶段提交 │
│ - Render 阶段:可中断,构建 Fiber 树 │
│ - Commit 阶段:不可中断,执行 DOM 操作 │
└──────────────────────────────────────────────────────────────────┘
这些机制共同作用,使 React 能够:
✓ 保持 UI 响应性
✓ 优先处理用户交互
✓ 支持并发特性
✓ 提供更好的用户体验
Fiber 是 React 现代特性的基础,包括:
- Concurrent Mode
- Suspense
- Transitions
- Server Components
- Offscreen Rendering
理解 Fiber 的工作原理对于:
- 编写高性能 React 应用
- 调试复杂问题
- 理解 React 内部机制
- 优化渲染性能
都具有重要意义。