React19 渲染流程

一、React 渲染架构

底层渲染流程大致可以分为两大阶段:render 阶段(Scheduler -> Reconciler)、commit 阶段(Renderer)

注意这里的 render 阶段和 Renderer 渲染器是两个东西!!!

主要的阶段可以总结为两个公式:

JavaScript 复制代码
const state = reconcile(update); // 通过 reconciler 计算出最新的状态
const UI = commit(state); // 通过最新的 state 渲染出 UI

二、调度器(Scheduler):渲染的入口与优先级控制

Scheduler 类似于浏览器的原生 API requestIdleCallback。React 团队没有使用 requestIdleCallback 是因为考虑为兼容性问题。

Scheduler 是整个渲染执行链条的入口,负责:

  1. 将变更转化为任务
  2. 按优先级调度任务执行
  3. 支持时间切片与可中断渲染

虽然每一帧绘制时间约为 16.66ms,但是如果屏幕没有刷新,那么浏览器会安排长度为 50ms 左右的空闲时间。

研究表明,用户操作之后,100ms 以内的响应给用户的感觉都是瞬间发生,也就是说不会感受到延迟感,因此将空闲时间设置为 50,浏览器依然还剩下 50ms 可以处理用户的操作响应,不会让用户感到延迟,这就是我们面试题中常看到的浏览器渲染每帧的空闲时间。

更新任务被排队

当你调用 setStatedispatchstartTransition、事件触发更新时,React 内部会:

Plain 复制代码
scheduleUpdateOnFiber(fiber, lane, eventTime)

这个函数是调度入口,它将更新附着在对应的 Fiber 上,并根据任务的 lane(内部优先级) 更新任务队列。

任务优先级系统(Lanes)

React 内部并不使用单一队列,而是用多 lane 机制。

优先级由 Scheduler 根据事件来源与延迟(expiration time)决定。

时间切片(Time Slicing)

Scheduler 会根据浏览器的空闲时间,决定是在当前帧继续执行还是 yield 给浏览器,这样协调器起点也是不同的:

  • performSyncWorkOnRoot(同步更新流程)
  • performConcurrentWorkOnRoot(并发更新流程)
JavaScript 复制代码
// performSyncWorkOnRoot 会执行该方法
function workLoopSync(){
  while(workInProgress !== null){
    performUnitOfWork(workInProgress)
  }
}
// performConcurrentWorkOnRoot 会执行该方法
function workLoopConcurrent() {
  // shouldYield 表明任务是否可以中断
  // 如果 workInProgress 为 null,说明已经没有下一个 FiberNode,也就是说明整颗 Fiber tree 树构建完毕
  while (workInProgress !== null && !shouldYield()) {
    // performUnitOfWork创建下一个 FiberNode,并且将已创建的 FiberNode 连接起来(child、return、sibling),形成一个链表结构的 Fiber tree
    workInProgress = performUnitOfWork(workInProgress); 
  }
}

shouldYield 判断当前帧是否该让出,避免阻塞主线程。

中断 + 恢复机制

如果有更高优先级的任务,中断当前 render,后续在合适时机 ​恢复执行​。这样能确保交互响应不会被大更新阻塞。

三、协调器(Reconciler):Fiber 树的 diff 与标记

协调器的核心任务是:

  1. 对比新旧树,确定哪些节点变化
  2. 生成 workInProgress Fiber 树
  3. 标记变化(Placement、Update、Deletion)
  4. 不直接修改 DOM,而是将变化收集起来

Fiber 数据结构

每一个组件在运行时都有一个 Fiber 节点:

  • 指向真实 DOM 实例
  • 链接 child / sibling / return 三个方向
  • 记录当前组件状态、props、更新队列、优先级等属性

这种结构不同于简单递归栈,它更像一颗​可分片执行的链表树​。

Reconciler 工作循环 ------ render 阶段

协调器是由 Scheduler 调度后执行的。React 会从 Root Fiber 开始 traverse。

a. beginWork

处理当前节点逻辑,根据类型(函数组件 / 类组件 / Fragment 等)判断需要构建哪些子 Fiber。

b. completeWork

在子节点构建完成后整合变化,把节点的更改标记写入 flags

JavaScript 复制代码
// 深度优先遍历
function performUnitOfWork(fiberNode){
  // 省略 beginWork 
  if(fiberNode.child){
    performUnitOfWork(fiberNode.child);
  }
  // 省略 CompleteWork 
  if(fiberNode.sibling){
    performUnitOfWork(fiberNode.sibling);
  }
}

整个过程构成一个 ​双缓冲机制​:

  • current Fiber(当前渲染状态)
  • workInProgress Fiber(正在构建的树)

最终 workInProgress 树会用于提交阶段。

标记变化

协调器不会直接操作 DOM,而是根据差异为每个节点打上 flags:

  • Placement:新节点插入
  • Update:属性/文本内容更新
  • Deletion:删除节点

这些标记会在提交阶段被 Renderer 读取。

四、渲染器(Renderer):真实环境应用变化

Renderer 是把协调阶段生成的变化同步应用到最终环境,比如:

  • 浏览器的 DOM
  • React Native 原生视图
  • 其他自定义渲染平台

React 通过隔离平台实现了 Renderer 的可插拔。相较于 render 阶段,此时 commit 阶段不可中断恢复。

提交阶段的三个子阶段

协调阶段完成后进入 ​commit 阶段​:

a. Before Mutation

执行 getSnapshotBeforeUpdate(类组件),记录焦点、selection(输入框光标)等。

JavaScript 复制代码
commitBeforeMutationEffects(root, finishedWork)
// 读取旧的 DOM 状态
b. Mutation

真实 DOM 操作发生位置 ​,根据 flags 做:appendChild、removeChild、update 属性、插入节点等。

然后切换 Fiber Tree(也就是上面提到的双缓冲机制,两棵树互换)。

c. Layout

useLayoutEffect 的意义是:在 DOM 更新完成后,浏览器绘制之前,同步读取或修改布局。

执行 useLayoutEffect、componentDidMount、componentDidUpdate 的回调。

注意哦!!!这里虽然 DOM 已经变更了,但是浏览器页面​还没有 paint,下一步才是绘制​。

渲染器应用 DOM 改变

JavaScript 复制代码
commitUpdate(domElement, updatePayload, type, oldProps, newProps)
// 调用一系列 DOM API 为元素属性更新赋值

这里 paint 之后,才会执行 useEffect(异步)的回调。

所以如果需要操作 DOM ,要在 useLayoutEffect 钩子执行。

相关推荐
橙子家8 小时前
浏览器缓存之【身份与会话管理】:Cookies 和 Private state tokens
前端
To_OC9 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
最新资讯动态9 小时前
HDC 2026 | 对话鲸鸿动能:存量时代,品牌如何夺回营销“主动权”?
前端
最新资讯动态9 小时前
游戏出海,从产品走向体系
前端
最新资讯动态10 小时前
20人团队跑出百万DAU、大厂也来抢量:谁在鸿蒙生态跑出加速度
前端
最新资讯动态10 小时前
千万开发者背后,鸿蒙商业化的B面
前端
爱勇宝12 小时前
AI 时代:智商决定起点,情商决定走多远
前端·ai编程
kyriewen12 小时前
用了半年 Claude Code 后,我尝试关掉它写了一周代码——结果比想象中严重
前端·javascript·ai编程
IT_陈寒13 小时前
Vite的静态资源打包让我熬夜到三点,这坑千万别跳
前端·人工智能·后端
山河木马13 小时前
矩阵专题0-webGL中的矩阵
javascript·webgl·计算机图形学