React Fiber 的意义

18 阅读3分钟

🎯 React Fiber 的出现

React16 之前的渲染模式是不可中断的,如果目前执行的任务过长,就会出现以下问题:

  • 用户点按钮半天没反应
  • 动画卡得像 PPT
  • 页面像被人按下了暂停键

为了解决 React 渲染不友好的问题,让 React 变得更灵活(被打断也可以继续),所以需要一个全新的运行时架构

  • 可切片
  • 可暂停
  • 可恢复
  • 可优先级调度

🧠 React Fiber 的定义

Fiber 是可中断的渲染引擎,是把组件更新变成“可暂停的工作单元”的调度系统。

更具体的理解就是:

  • Fiber 是一种链表结构的 vnode
  • 它把每一个组件渲染拆成任务单元(unit of work)
  • 所有任务都会被调度器按照优先级先后处理

🧩 React Fiber 的关键能力

💪 1. 可中断渲染(Time Slicing)

之前现在
渲染不可中断,会阻塞其他事件,如用户点击等渲染可中断,在任务执行过程中随时会给浏览器让步,等高优任务结束后再恢复执行

🎚️ 2. 优先级调度(Scheduler)

React Fiber 会给每个更新都贴上“优先级标签”,像这样:

更新类型优先级(lane)
用户点击🟥 超高优先级
输入框输入🟧 很高
普通渲染🟩 中等
transition🟦 低一点
日志、统计🟪 淡淡的随缘优先级

用户点击了按钮 => 触发最高lane 任务 异步数据回来 => 触发中等lane任务 transition动效更新 => 触发更低lane任务

React 会根据这些任务的 lane 来决定当前应该执行哪个任务,以及后续任务的执行顺序。

🐱 3. 可恢复渲染(Pause & Resume)

React Fiber 中的每个节点都是一个 Fiber 对象,每次渲染一个 Fiber,都会在调度器中记录一个TODO List

Fiber A:处理中...
Fiber B:处理中...
Fiber C:处理中...
--给浏览器让步--
Fiber D:继续处理...

🔁 4. 双缓冲结构(alternate)

每个 Fiber 对象都有一个 alternate指针,分别指向两棵树:

  • current:现在正在屏幕上的版本
  • workInProgress:正在构建的新版本

渲染期间 React 在 workInProgress 上完成所有的 diff 对比及更新操作,等渲染完毕后再将所有更改全部更新到current上面。

🧱 React Fiber 的执行流程

整个更新流程参考图如下所示:

🐱 1. 触发更新(setState / dispatch)  
       ↓
🐱 2. 调度(分配 lane优先级)  
       ↓
🐱 3. render 阶段(可中断)
      - beginWork(创建新 fiber)
      - completeWork(收集副作用 flags)
       ↓
🐱 4. commit 阶段(不可中断)
      - mutation:动 DOM
      - layout:执行 layout effect
      - passive:执行普通 effect

render 可以被打断,commit 绝对不会被打断

因为 commit 阶段动 DOM 和副作用,不能搞一半停一半,不然页面要变成“半成品料理”。

🎚️ 调度系统(Scheduler)

React 其内部会周期性调用 shouldYield() 询问浏览器是否需要让步,如果浏览器需要渲染动画、响应用户操作,React 会暂停自己的渲染工作。

如果让步:

pause → 等下再继续 → resume

🏎 lane 模型

在 Fiber 内部,每个更新会被标记成 lane:

00001 → 高优先级更新
00010 → 普通更新
00100transition
01000 → 空闲任务
…

比如来了一个点击事件(超高优先级):

pendingLanes = 00001

React 检查当前渲染是否比它慢:

  • 若慢,立即 中断当前渲染
  • 处理高优先级任务
  • 再回来继续做之前没做完的

🎤 总结

  1. “Fiber 就是一个可以被切片、暂停、恢复的渲染引擎,它把每个组件拆成可调度的工作单元,并用 lane 模型管理优先级,让 React 能在高负载下保持流畅的用户交互。”
  2. “render 阶段可中断,commit 阶段不可中断,这是保证用户看到 UI 一致性的关键。”
  3. “双缓冲结构让 React 可以在后台构建新的 UI,再一次性替换出来。”

“时间切片让渲染不再阻塞用户输入。”