基于 React 源码深度解析
2026-03-15 | 技术深度解读
第一部分:基础架构
第二部分:核心数据结构
第三部分:核心函数
第四部分:调度与优化
Reconciler(协调器) 是 React 渲染架构的核心,负责决定哪些组件需要更新以及如何更新。
核心职责
设计目标
┌─────────────────────────────────────────────┐
│ React 渲染架构 │
├─────────────────────────────────────────────┤
│ Scheduler (调度器) │
│ ↓ 调度任务 │
│ ┌─────────────────────────────────────────┐│
│ │ Reconciler (协调器) ⭐ ││
│ │ • beginWork - 向下遍历 ││
│ │ • completeWork - 向上回溯 ││
│ │ • reconcileChildFibers - 子节点协调 ││
│ └─────────────────────────────────────────┘│
│ ↓ 生成 Effect List │
│ ┌─────────────────────────────────────────┐│
│ │ Renderer (渲染器) ││
│ │ • commitMutationEffects ││
│ │ • DOM/原生平台操作 ││
│ └─────────────────────────────────────────┘│
└─────────────────────────────────────────────┘
1. Render Phase(渲染阶段) - 纯计算,可中断
2. Pre-commit Phase(预提交) - 读取 DOM 状态
3. Commit Phase(提交阶段) - 真实 DOM 操作,不可中断
| 阶段 | 可中断 | 核心函数 | 产出 |
|---|---|---|---|
| Render | ✅ 是 | beginWork/completeWork | 新的 Fiber 树 + Effect List |
| Pre-commit | ❌ 否 | commitBeforeMutationEffects | 读取 DOM 快照 |
| Commit | ❌ 否 | commitMutationEffects | 真实 DOM 更新 |
Render 阶段是协调的核心,通过深度优先遍历 Fiber 树来计算差异。
// Render 阶段核心循环
function workLoopConcurrent() {
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}
function performUnitOfWork(unitOfWork: Fiber): void {
const current = unitOfWork.alternate;
// 1. beginWork - 处理当前节点
let next = beginWork(current, unitOfWork, renderLanes);
if (next === null) {
// 2. completeWork - 没有子节点,开始回溯
completeUnitOfWork(unitOfWork);
} else {
workInProgress = next; // 继续处理子节点
}
}
Commit 阶段是不可中断的同步操作,将计算结果应用到真实 DOM。
// Commit 阶段三个子阶段
function commitRoot(root: FiberRoot, recoverableErrors: ...) {
// 1. Before Mutation (读取 DOM 状态)
commitBeforeMutationEffects(root, finishedWork);
// 2. Mutation (DOM 操作)
commitMutationEffects(root, finishedWork);
// 3. Layout (布局后同步执行)
commitLayoutEffects(root, finishedWork);
// 触发 passive effects (useEffect)
scheduleCallback(NormalPriority, () => {
flushPassiveEffects();
});
}
| 类/接口 | 文件 | 职责 |
|---|---|---|
| Fiber | ReactFiber.js | 虚拟 DOM 节点 |
| FiberRoot | ReactFiberRoot.js | 根容器状态 |
| Lane | ReactFiberLane.js | 优先级模型 |
| Flags | ReactFiberFlags.js | 副作用标记 |
| WorkTag | ReactWorkTags.js | 组件类型标识 |
// ReactFiber.js - Fiber 节点构造函数
function FiberNode(
tag: WorkTag, // 组件类型
pendingProps: mixed, // 待处理 props
key: null | string, // React key
mode: TypeOfMode, // 渲染模式
) {
// Instance 字段
this.tag = tag;
this.key = key;
this.elementType = null;
this.type = null;
this.stateNode = null; // 对应的真实 DOM/组件实例
// Fiber 树结构(链表)
this.return = null; // 父节点
this.child = null; // 第一个子节点
this.sibling = null; // 下一个兄弟节点
this.index = 0; // 在父节点中的索引
// ... 更多字段
}
状态字段
pendingProps - 新 propsmemoizedProps - 上次 propsupdateQueue - 更新队列memoizedState - Hooks 链表dependencies - 依赖上下文副作用字段
flags - 副作用标记subtreeFlags - 子树标记deletions - 待删除子节点lanes - 优先级alternate - 双缓冲指针// 双缓冲:current 和 workInProgress 互相指向
let workInProgress = current.alternate;
workInProgress.alternate = current;
// ReactFiberRoot.js - 根容器
type FiberRoot = {
tag: RootTag, // LegacyRoot | ConcurrentRoot
containerInfo: Container, // DOM 容器
pendingChildren: any, // 子容器
current: Fiber, // 当前的 Fiber 树
// 工作队列
finishedWork: Fiber | null, // 已完成的 workInProgress
finishedLanes: Lanes, // 完成的优先级
// 调度状态
callbackNode: any, // 调度任务
callbackPriority: Lane, // 调度优先级
// 挂起的更新
pendingLanes: Lanes, // 待处理优先级
suspendedLanes: Lanes, // 挂起优先级
pingedLanes: Lanes, // 已唤醒优先级
};
// ReactWorkTags.js - 组件类型标识
export const FunctionComponent = 0; // 函数组件
export const ClassComponent = 1; // 类组件
export const HostRoot = 3; // 根节点
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 ContextProvider = 10; // Context.Provider
export const ContextConsumer = 9; // Context.Consumer
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
// ReactFiberFlags.js - 副作用标记(位掩码)
export const NoFlags = /* */ 0b0000000000000000;
export const PerformedWork = /* */ 0b0000000000000001;
export const Placement = /* */ 0b0000000000000010; // 插入
export const Update = /* */ 0b0000000000000100; // 更新
export const ChildDeletion = /* */ 0b0000000000001000; // 删除子节点
export const ContentReset = /* */ 0b0000000000010000; // 内容重置
export const Callback = /* */ 0b0000000000100000; // 回调
export const DidCapture = /* */ 0b0000000001000000; // 捕获错误
export const Ref = /* */ 0b0000000010000000; // Ref 更新
export const Snapshot = /* */ 0b0000000100000000; // 快照
export const Passive = /* */ 0b0000001000000000; // useEffect
export const Visibility = /* */ 0b0000010000000000; // 可见性
Lane 模型是 React 18 引入的优先级系统,用 31 位二进制表示不同的优先级级别。
// ReactFiberLane.js - 优先级模型
export const TotalLanes = 31;
export const NoLanes: Lanes = 0b0000000000000000000000000000000;
export const NoLane: Lane = 0b0000000000000000000000000000000;
// 同步优先级(最高)
export const SyncLane: Lane = 0b0000000000000000000000000000010;
// 连续输入(如 mousemove)
export const InputContinuousLane: Lane = 0b0000000000000000000000000001000;
// 默认优先级
export const DefaultLane: Lane = 0b0000000000000000000000000100000;
// 过渡优先级(startTransition)
const TransitionLanes: Lanes = 0b0000000001111111111111100000000;
// 空闲优先级(最低)
export const IdleLane: Lane = 0b0010000000000000000000000000000;
| Lane | 优先级 | 使用场景 |
|---|---|---|
| SyncLane | 最高 | 同步渲染、用户输入 |
| InputContinuousLane | 高 | 连续输入(拖拽、滚动) |
| DefaultLane | 中 | 普通更新 |
| TransitionLane | 低 | startTransition 包装的更新 |
| IdleLane | 最低 | 空闲时执行 |
核心原则:高优先级更新可以打断低优先级更新
// ReactFiberBeginWork.js - 向下遍历处理节点
function beginWork(
current: Fiber | null, // 当前显示的 Fiber
workInProgress: Fiber, // 正在构建的 Fiber
renderLanes: Lanes, // 当前渲染优先级
): Fiber | null {
// 检查是否可以复用(bailout)
if (current !== null) {
const oldProps = current.memoizedProps;
const newProps = workInProgress.pendingProps;
if (oldProps === newProps && !checkScheduledUpdateDidRender()) {
// Props 未变化,且无更新 → 复用子树
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
}
}
// 根据 tag 分发到不同处理函数
switch (workInProgress.tag) {
case FunctionComponent: return updateFunctionComponent(...);
case ClassComponent: return updateClassComponent(...);
case HostComponent: return updateHostComponent(...);
// ...
}
}
beginWork 处理流程:
┌─────────────────────────────────────┐
│ 进入 beginWork │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 检查是否可以 bailout(复用) │
│ • props 是否相同? │
│ • 是否有待处理的更新? │
└─────────────────────────────────────┘
↓ 否 ↓ 是
┌───────────────────┐ ┌──────────────┐
│ 根据 tag 执行 │ │ bailout 复用 │
│ 对应的 update 函数 │ │ 返回 null │
└───────────────────┘ └──────────────┘
↓
┌─────────────────────────────────────┐
│ reconcileChildren(协调子节点) │
│ • 单节点:reconcileSingleElement │
│ • 数组:reconcileChildrenArray │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 返回第一个子 Fiber(继续向下遍历) │
└─────────────────────────────────────┘
// ReactFiberCompleteWork.js - 向上回溯处理节点
function completeWork(
current: Fiber | null,
workInProgress: Fiber,
renderLanes: Lanes,
): Fiber | null {
const newProps = workInProgress.pendingProps;
switch (workInProgress.tag) {
case HostComponent: {
// 原生 DOM 元素
if (current !== null && workInProgress.stateNode != null) {
// 更新场景:标记 Update flag
updateHostComponent(current, workInProgress, type, newProps);
} else {
// 挂载场景:创建 DOM 实例
const instance = createInstance(type, newProps, ...);
workInProgress.stateNode = instance;
appendAllChildren(instance, workInProgress);
}
break;
}
// ... 其他类型处理
}
}
completeWork 处理流程:
┌─────────────────────────────────────┐
│ 进入 completeWork │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 根据 tag 执行对应的完成处理 │
│ • HostComponent: 创建/更新 DOM │
│ • HostText: 创建文本节点 │
│ • ClassComponent: 处理生命周期 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 冒泡副作用 flags 到父节点 │
│ workInProgress.return.flags |= │
│ workInProgress.subtreeFlags │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 返回兄弟节点或父节点 │
│ sibling || return │
└─────────────────────────────────────┘
// ReactFiberCommitWork.js - 提交副作用
function commitRoot(
root: FiberRoot,
recoverableErrors: Array<mixed>,
transientUpdates: Array<mixed> | null,
) {
// 阶段 1: Before Mutation
commitBeforeMutationEffects(root, finishedWork);
// - getSnapshotBeforeUpdate
// - schedule useEffect
// 阶段 2: Mutation
commitMutationEffects(root, finishedWork);
// - 插入/更新/删除 DOM
// - ref 更新
// 阶段 3: Layout
commitLayoutEffects(root, finishedWork);
// - componentDidMount/Update
// - useLayoutEffect
}
// DOM 操作的核心函数
function commitMutationEffects(
root: FiberRoot,
finishedWork: Fiber,
) {
// 遍历 Effect List
commitMutationEffects_begin(finishedWork, root);
}
function commitMutationEffectsOnFiber(
finishedWork: Fiber,
root: FiberRoot,
) {
const flags = finishedWork.flags;
// 处理 Placement(插入)
if (flags & Placement) {
commitPlacement(finishedWork);
finishedWork.flags &= ~Placement;
}
// 处理 Update(更新)
if (flags & Update) {
commitUpdate(finishedWork);
finishedWork.flags &= ~Update;
}
// 处理 ChildDeletion(删除)
if (flags & ChildDeletion) {
const deletions = finishedWork.deletions;
deletions.forEach(child => commitDeletion(child, root));
}
}
// ReactChildFiber.js - 子节点协调的核心
function reconcileChildFibers(
returnFiber: Fiber,
currentFirstChild: Fiber | null,
newChild: any,
lanes: Lanes,
): Fiber | null {
// 判断子节点类型
if (typeof newChild === 'object' && newChild !== null) {
switch (newChild.$$typeof) {
case REACT_ELEMENT_TYPE:
// 单个 React 元素
return reconcileSingleElement(...);
case REACT_PORTAL_TYPE:
return reconcileSinglePortal(...);
}
if (isArray(newChild)) {
// 数组子节点
return reconcileChildrenArray(...);
}
}
if (typeof newChild === 'string' || typeof newChild === 'number') {
// 文本子节点
return reconcileSingleTextNode(...);
}
// 其他情况返回 null
return deleteRemainingChildren(returnFiber, currentFirstChild);
}
| 子节点类型 | 处理函数 | 说明 |
|---|---|---|
| 单个元素 | reconcileSingleElement | 创建或复用单个子节点 |
| 文本节点 | reconcileSingleTextNode | 处理纯文本子节点 |
| 数组 | reconcileChildrenArray | Diff 算法的核心 |
| Iterator | reconcileChildrenIterator | 处理可迭代对象 |
关键:React 的 Diff 算法只处理数组场景,遵循"同层级比较"原则
// 首次渲染时,current 为 null
function mountChildFibers(
returnFiber: Fiber,
newChild: any,
lanes: Lanes,
): Fiber | null {
// 没有旧 Fiber,直接创建新 Fiber
// 不需要 Diff,所有节点都是新的
if (typeof newChild === 'object' && newChild !== null) {
switch (newChild.$$typeof) {
case REACT_ELEMENT_TYPE:
return createFiberFromElement(newChild, returnFiber.mode, lanes);
}
if (isArray(newChild)) {
// 数组:依次创建,标记 Placement
return createChildReconciler(false)(returnFiber, null, newChild, lanes);
}
}
}
// mountChildFibers 和 reconcileChildFibers 的区别:
// - mountChildFibers: currentFirstChild = null, 不标记 Placement
// - reconcileChildFibers: currentFirstChild 不为 null, 需要 Diff
mountChildFibers
reconcileChildFibers
Diff 三原则:
// ReactFiberWorkLoop.js - 工作循环
function workLoopConcurrent() {
// 可中断的工作循环
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}
function workLoopSync() {
// 同步工作循环(不可中断)
while (workInProgress !== null) {
performUnitOfWork(workInProgress);
}
}
// shouldYield() 来自 Scheduler
// 检查当前帧是否还有剩余时间
function shouldYield(): boolean {
return getCurrentTime() >= deadline;
}
// 并发模式下的工作循环
function workLoopConcurrent() {
// 循环条件:
// 1. 还有待处理的 Fiber
// 2. 时间片未用完(shouldYield = false)
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
// 循环结束后检查
if (workInProgress !== null) {
// 被中断,需要恢复
root.callbackNode = scheduleCallback(
workInProgressRootPriority,
performConcurrentWorkOnRoot.bind(null, root)
);
} else {
// 完成,进入 commit 阶段
finishConcurrentRender(root, finishedWork);
}
}
// 处理单个 Fiber 单元
function performUnitOfWork(unitOfWork: Fiber): void {
const current = unitOfWork.alternate;
// 1. beginWork: 向下遍历
let next = beginWork(current, unitOfWork, renderLanes);
// 重置 pendingProps(已处理)
unitOfWork.memoizedProps = unitOfWork.pendingProps;
if (next === null) {
// 没有子节点,开始回溯
completeUnitOfWork(unitOfWork);
} else {
// 有子节点,继续向下
workInProgress = next;
}
}
// 深度优先遍历顺序:
// beginWork(A) → beginWork(B) → beginWork(C)
// → completeWork(C) → completeWork(B) → completeWork(A)
React 使用 Scheduler 进行任务调度,基于 Lane 模型管理优先级。
// 调度更新
function scheduleUpdateOnFiber(root: FiberRoot, fiber: Fiber, lane: Lane) {
// 1. 标记更新优先级
markRootUpdated(root, lane);
// 2. 确保已调度
ensureRootIsScheduled(root);
}
function ensureRootIsScheduled(root: FiberRoot) {
// 获取最高优先级的 Lane
const nextLanes = getNextLanes(root);
// 如果已有调度且优先级相同,复用
if (existingCallbackPriority === nextLanes) {
return;
}
// 调度新任务
const newCallbackNode = scheduleCallback(
priorityLevel,
performConcurrentWorkOnRoot.bind(null, root)
);
root.callbackNode = newCallbackNode;
}
React 使用双缓冲(Double Buffering)来维护两棵 Fiber 树:
// 双缓冲示意图
FiberRoot
│
↓ current
┌─────────────┐
│ current 树 │ ← 当前显示的树
│ (Fiber) │
└─────────────┘
↑
alternate
│
┌─────────────┐
│ workInProgress│ ← 正在构建的树
│ (Fiber) │
└─────────────┘
// Render 阶段完成后
root.current = finishedWork; // 切换指针
// 双缓冲的好处:
// 1. 避免在构建过程中显示不完整的 UI
// 2. 可以复用上一次的 Fiber 节点
// 3. 支持中断和恢复
// completeWork 中冒泡副作用
function completeUnitOfWork(unitOfWork: Fiber): void {
let completedWork = unitOfWork;
do {
// 1. 完成当前节点
completeWork(current, completedWork, renderLanes);
// 2. 收集子节点的副作用
const subtreeFlags = completedWork.subtreeFlags;
const flags = completedWork.flags;
// 3. 冒泡到父节点
const returnFiber = completedWork.return;
if (returnFiber !== null) {
returnFiber.subtreeFlags |= subtreeFlags | flags;
returnFiber.flags |= subtreeFlags;
}
// 4. 处理兄弟节点
const siblingFiber = completedWork.sibling;
if (siblingFiber !== null) {
workInProgress = siblingFiber;
return; // 处理兄弟
}
completedWork = returnFiber; // 回溯到父节点
} while (completedWork !== null);
}
React Reconciler 中应用了多种经典设计模式:
结构型模式
行为型模式
// Fiber 树使用链表结构
class Fiber {
return: Fiber | null; // 父节点指针
child: Fiber | null; // 第一个子节点
sibling: Fiber | null; // 下一个兄弟节点
}
// 遍历示例
function traverseFiber(fiber: Fiber) {
// 处理当前节点
visit(fiber);
// 递归遍历子节点
let child = fiber.child;
while (child !== null) {
traverseFiber(child);
child = child.sibling; // 通过 sibling 访问下一个子节点
}
}
// 链表的好处:
// 1. 内存效率高(不需要数组)
// 2. 插入/删除 O(1)
// 3. 支持可中断遍历
// Flags 使用位掩码
export const NoFlags = 0;
export const Placement = 0b00000010;
export const Update = 0b00000100;
export const ChildDeletion = 0b00001000;
// 设置标记
fiber.flags |= Placement | Update;
// 检查标记
if (fiber.flags & Placement) {
// 需要插入
}
// 清除标记
fiber.flags &= ~Placement;
// 位掩码的好处:
// 1. 内存效率高(一个数字存储多个标记)
// 2. 操作速度快(位运算)
// 3. 支持组合检查
// Lane 模型也使用位掩码
const allSyncLanes = SyncLane | InputContinuousLane | DefaultLane;
// Scheduler 是独立的调度器包
import { scheduleCallback, shouldYield } from './Scheduler';
// 任务队列(最小堆)
const taskQueue: Array<Task> = [];
// 调度任务
function scheduleCallback(priority, callback) {
const task = {
callback,
priority,
expirationTime: currentTime + timeout,
};
push(taskQueue, task); // 放入最小堆
requestHostCallback(); // 请求执行
}
// 工作循环
function workLoop() {
while (taskQueue.length > 0) {
if (shouldYield()) break; // 时间片用完
const task = peek(taskQueue);
task.callback();
pop(taskQueue);
}
}
┌───────────────┐ ┌───────────────┐
│ FiberRoot │ │ Fiber │
├───────────────┤ ├───────────────┤
│ current │───┐ │ tag │
│ containerInfo │ │ │ key │
│ pendingLanes │ │ │ return │────┐
│ callbackNode │ │ │ child │────┼──┐
└───────────────┘ │ │ sibling │←───┘ │
│ │ alternate │←──────┼──┐
│ │ flags │ │ │
│ │ lanes │ │ │
│ └───────────────┘ │ │
│ │ │
└───────────────────────────┘ │
│ │
└──────────────────────────┘
(双缓冲:current ↔ workInProgress)
触发更新 (setState/dispatch)
│
↓
┌─────────────────────┐
│ scheduleUpdateOnFiber│
│ 标记 Lane,调度任务 │
└─────────────────────┘
│
↓
┌─────────────────────┐
│ ensureRootIsScheduled│
│ 根据优先级调度 │
└─────────────────────┘
│
↓
┌─────────────────────┐
│ performConcurrentWork│
│ Render 阶段开始 │
└─────────────────────┘
│
┌────┴────┐
↓ ↓
beginWork completeWork
(向下遍历) (向上回溯)
│ │
└────┬────┘
↓
┌─────────────────────┐
│ commitRoot │
│ Commit 阶段 │
└─────────────────────┘
A (beginWork)
/ \
B C (beginWork)
/ \
D E (beginWork)
│ │
(complete) (complete)
│ │
D E ← completeWork
│
(complete)
│
B ← completeWork
│
C ← completeWork
│
A ← completeWork
// 遍历顺序:A→B→D→D完成→B完成→C→E→E完成→C完成→A完成
// 典型的深度优先遍历(DFS)
commitRoot
│
├─→ commitBeforeMutationEffects
│ │
│ ├─→ getSnapshotBeforeUpdate (Class)
│ └─→ scheduleCallback (useEffect)
│
├─→ commitMutationEffects
│ │
│ ├─→ commitPlacement (插入)
│ ├─→ commitUpdate (更新)
│ └─→ commitDeletion (删除)
│
└─→ commitLayoutEffects
│
├─→ componentDidMount/Update (Class)
├─→ useLayoutEffect
└─→ ref.callback
然后异步执行 → flushPassiveEffects (useEffect)
setState 调用
│
↓
┌────────────────────┐
│ requestUpdateLane │ ← 根据事件类型获取 Lane
│ - Discrete: Sync │
│ - Continuous: Input│
│ - Default: Default │
│ - Transition: Trans│
└────────────────────┘
│
↓
┌────────────────────┐
│ enqueueUpdate │ ← 将 update 加入队列
│ fiber.updateQueue │
└────────────────────┘
│
↓
┌────────────────────┐
│ scheduleUpdateOnFiber│ ← 标记 root.pendingLanes
│ markRootUpdated │
└────────────────────┘
│
↓
┌────────────────────┐
│ getNextLanes │ ← 获取最高优先级
│ 调度对应优先级任务 │
└────────────────────┘
调度优化
渲染优化
核心原则:减少不必要的重新渲染
// Scheduler 的时间切片实现
const frameInterval = 5; // 5ms 时间片
function shouldYield(): boolean {
const currentTime = getCurrentTime();
const deadline = startTime + frameInterval;
return currentTime >= deadline;
}
// React 中的使用
function workLoopConcurrent() {
while (workInProgress !== null) {
if (shouldYield()) {
// 时间片用完,保存状态并退出
root.callbackNode = scheduleCallback(
priority,
performConcurrentWorkOnRoot.bind(null, root)
);
return;
}
performUnitOfWork(workInProgress);
}
}
// 好处:保持 UI 响应,不阻塞用户交互
// 自动批量更新(React 18)
function handleClick() {
// 这些更新会被批量处理
setCount(c => c + 1);
setFlag(f => !f);
// 只触发一次重新渲染
}
// 原理:共享同一个 Lane
function batchedUpdates(fn) {
const prevExecutionContext = executionContext;
executionContext |= BatchedContext;
try {
return fn();
} finally {
executionContext = prevExecutionContext;
// 离开批量上下文时才调度
if (executionContext === NoContext) {
flushSyncCallbacks();
}
}
}
// beginWork 中的 bailout 检查
function beginWork(current, workInProgress, renderLanes) {
// 条件 1: current 存在(非首次渲染)
// 条件 2: props 相同
// 条件 3: 没有待处理的更新
if (current !== null) {
const oldProps = current.memoizedProps;
const newProps = workInProgress.pendingProps;
if (oldProps === newProps &&
!checkHasForceUpdateAfterProcessing()) {
// 复用整个子树
return bailoutOnAlreadyFinishedWork(
current, workInProgress, renderLanes
);
}
}
// ... 正常处理
}
// React.memo 的作用就是阻止 props 变化时的重渲染
// 使得 bailout 条件更容易满足
组件设计
状态管理
避免这些常见错误:
// ❌ 在渲染中产生副作用
function Component() {
document.title = 'Bad'; // 副作用!
return <div>...</div>;
}
// ❌ 过度使用 memo
const MemoChild = memo(Child); // 不总是需要
// ❌ 不稳定的 key
{items.map(item => (
<Item key={Math.random()} /> // 每次都重建
))}
// ❌ 在 useEffect 中直接修改 state
useEffect(() => {
setState(derived); // 可能导致循环
}, [dependency]);
// ❌ 同步阻塞操作
function handleClick() {
heavyComputation(); // 阻塞渲染
}
// React DevTools Profiler
// 查看 Flamegraph 和 Ranked 视图
// 使用 React 内置的日志
// 在 React 源码中设置断点
// 关键断点位置:
// - beginWork (ReactFiberBeginWork.js)
// - completeWork (ReactFiberCompleteWork.js)
// - commitMutationEffects (ReactFiberCommitWork.js)
// - reconcileChildFibers (ReactChildFiber.js)
// 使用 React 的 __DEV__ 标志
if (__DEV__) {
console.log('Current fiber:', current);
console.log('Work in progress:', workInProgress);
console.log('Flags:', flags);
}
// 查看调度状态
// Scheduler.unstable_getCurrentPriorityLevel()
| 特性 | React | Vue |
|---|---|---|
| 响应式系统 | 不可变 + Diff | Mutable + Proxy |
| 更新粒度 | 组件级 | 依赖追踪到具体属性 |
| 调度 | 基于 Lane 优先级 | 基于 job queue |
| 虚拟 DOM | Fiber 树 | VNode 树 |
| 时间切片 | 支持(并发模式) | 有限支持 |
React 19+
架构演进
核心要点回顾:
关键文件:ReactFiberWorkLoop.js, ReactFiberBeginWork.js, ReactChildFiber.js, ReactFiberLane.js
官方文档
深度文章
🔗 源码地址:github.com/facebook/react
📍 核心路径:packages/react-reconciler/src/