React 的 “大脑” 与 “双手”:Render 阶段(大脑)算好怎么改,Commit 阶段(双手)动手改 DOM

28 阅读3分钟

React 的更新流程分为 ​​Render 阶段​​(协调阶段)和 ​​Commit 阶段​​(提交阶段),两者共同完成组件更新。以下是每个阶段的核心职责和实现细节:


​一、Render 阶段(协调阶段)​

​目标​​:生成更新计划(副作用链表),不直接操作 DOM
​特性​​:可中断、异步执行(并发模式核心)

​核心流程​​:

  1. ​触发更新​​:

    • setStateuseState、父组件渲染等触发更新
    • 创建 Update 对象,加入 Fiber 的更新队列
  2. ​调度优先级​​:

    • 根据更新来源(用户交互、网络响应等)分配优先级(如 ImmediateUserBlocking
    • 通过 scheduler 调度任务
  3. ​协调算法(Reconciliation)​​:

    graph TD
        A[根节点开始] --> B{是否还有子节点?}
        B -->|是| C[处理当前Fiber节点]
        C --> D[比较新旧props/state]
        D --> E[标记副作用Tag]
        E --> B
        B -->|否| F[完成协调]
    
    • ​深度优先遍历​​:从根节点开始遍历 Fiber 树
    • ​Diff 算法​​:对比新旧 ReactElement,生成子 Fiber 树
    • ​副作用标记​​:对需要 DOM 操作的节点打标记(如 PlacementUpdateDeletion
  4. ​收集副作用​​:

    • 构建副作用链表(effectList),链表节点包含所有需要 DOM 操作的 Fiber

​关键代码​​:

function performUnitOfWork(fiber) {
  // 1. 执行组件渲染(生成子Fiber)
  const children = reconcileChildren(fiber, fiber.props.children);
  
  // 2. Diff算法比较新旧子节点
  reconcileChildFibers(fiber, children);
  
  // 3. 返回下一个工作单元(深度优先)
  if (fiber.child) return fiber.child;
  let nextFiber = fiber;
  while (nextFiber) {
    if (nextFiber.sibling) return nextFiber.sibling;
    nextFiber = nextFiber.return;
  }
}

​二、Commit 阶段(提交阶段)​

​目标​​:将 Render 阶段的更新计划同步应用到 DOM
​特性​​:同步执行、不可中断(防止页面状态不一致)

​核心流程​​:

  1. ​预处理​​:

    • 调用 getSnapshotBeforeUpdate 生命周期(获取 DOM 更新前的状态)
  2. ​DOM 操作​​:

    graph TD
        A[遍历effectList] --> B{操作类型}
        B -->|Placement| C[插入DOM]
        B -->|Update| D[更新DOM属性]
        B -->|Deletion| E[删除DOM]
        C --> F
        D --> F
        E --> F[完成所有DOM操作]
    
    • 实际执行 DOM 增删改操作
    • 处理 ref 的绑定/解绑
  3. ​生命周期与副作用​​:

    • 同步执行:componentDidMountcomponentDidUpdate
    • 异步调度:useEffect 副作用(通过 scheduleCallback 调度)
  4. ​状态清理​​:

    • 重置 Fiber 树的副作用标记
    • 准备下一次更新的 current

​关键代码​​:

function commitRoot(root) {
  // 1. 处理DOM插入/更新/删除
  commitMutationEffects(root.effectList);
  
  // 2. 执行生命周期
  commitLayoutEffects(root.effectList);
  
  // 3. 调度useEffect
  schedulePendingEffects();
}

​三、阶段对比​

​特性​​Render 阶段​​Commit 阶段​
​操作对象​Fiber 树(虚拟节点)真实 DOM
​可中断性​是(并发模式)
​副作用​收集副作用(effectList)执行副作用(DOM操作/生命周期)
​优先级​支持优先级插队无优先级,必须同步完成
​生命周期​componentDidMount/Update
​主要耗时​计算 DiffDOM 操作

​四、示例流程​

假设组件树更新:

// 更新前
<div>
  <span key="1">Old</span>
</div>

// 更新后
<div>
  <span key="1">New</span>
  <p key="2">New</p>
</div>
  1. ​Render 阶段​​:

    • 比较新旧节点,标记 <span>Update<p>Placement
    • 生成 effectList[spanFiber, pFiber]
  2. ​Commit 阶段​​:

    • 更新 <span> 的文本内容
    • 插入新 <p> 节点到 <div>

​五、设计意义​

  1. ​并发模式基础​​:Render 阶段可中断,确保高优先级任务(如用户输入)及时响应
  2. ​性能优化​​:分离计算和 DOM 操作,避免计算阻塞渲染
  3. ​一致性保证​​:Commit 阶段一次性提交,防止中间状态暴露

通过这种两阶段设计,React 平衡了性能与一致性,为复杂应用的流畅体验提供底层保障。