焦作市网站建设_网站建设公司_CMS_seo优化
2025/12/22 16:24:35 网站建设 项目流程

Fiber 的核心目标——把一次“不可中断的递归渲染”,拆成“可中断、可恢复、可优先级调度的工作单元”

一、为什么 React 要引入 Fiber?

老架构(Stack Reconciler)的问题,React 16 之前:

  • diff + render 是一次性同步递归
  • JS 线程被长期占用
  • 浏览器:
    • ❌ 不能响应用户输入
    • ❌ 不能渲染动画
    • ❌ 会卡顿、掉帧

📌 本质问题:React 没法“暂停 / 打断 / 恢复”渲染

二、核心概念

Fiber 是 React 内部对“组件/DOM 节点”的一种可调度的执行单元(Work Unit)

不是虚拟 DOM 本身,而是:

  • 虚拟 DOM + 运行时控制信息
  • 数据结构 + 执行上下文

三、Fiber 的核心数据结构

一个 Fiber 本质是一个对象:

interface Fiber {// 节点类型tag: WorkTag;// 对应的组件或 DOMtype: any;stateNode: any;// Fiber 树结构return: Fiber | null;  // 父child: Fiber | null;   // 第一个子sibling: Fiber | null; // 下一个兄弟// 状态相关(Hooks 在这)memoizedState: any;updateQueue: UpdateQueue<any> | null;// propspendingProps: any;memoizedProps: any;// 副作用flags: Flags;subtreeFlags: Flags;// 双缓存alternate: Fiber | null;
}

一些关键点:

  1. 树结构是 链表式的,为了能中断遍历,而不是递归调用栈
child → sibling → sibling
  1. alternate:Fiber 的灵魂,“并发渲染不撕裂 UI”的关键
current Fiber  ←→  workInProgress Fiber
  • current:当前屏幕显示的
  • wip:正在计算的新版本
  1. Hooks 存在哪里?useState 不是存在闭包,而是存在 Fiber 上
fiber.memoizedState // Hooks 单向链表

四、Fiber 架构下的两大阶段

这两个阶段正是组件渲染的两个阶段:

  1. 父组件渲染导致子组件渲染(默认行为)
  2. 组件内状态更新
  3. context 改变导致使用 useContext 的组件更新

1️⃣ Render 阶段(Reconciliation 协调阶段)

做什么?

  • 创建 / 复用 Fiber(diff 过程)
  • 执行函数组件
  • 计算新 state,运行 useState,useMemo,useCallback
  • 标记副作用(flags),生成更新链表

特点:

  • ✅ 可打断
  • ❌ 不操作 DOM
  • ❌ 不执行副作用
beginWork↓
completeWork

2️⃣ Commit 阶段(提交阶段 / 实际 DOM 操作)

分三步:

  1. before mutation(提交前)

执行:

  • getSnapshotBeforeUpdate
  • 调整内容前的准备
  1. mutation(变更 DOM)

执行所有 DOM 操作:

  • 插入 DOM
  • 删除 DOM
  • 修改 DOM 属性
  • ref 的更新
  1. layout(布局阶段)

执行 Layout Effects:

  • useLayoutEffect 回调
  • class 组件的 componentDidMount / componentDidUpdate

Mutation 和 Layout 这两步是同步执行的,不允许中断。

总结下,上述做了什么?

  • 更新 DOM
  • 执行 useEffect / useLayoutEffect(componentDidMount)
  • ref 赋值

特点:

  • ❌ 不可中断
  • ✅ 必须一次完成

Render 阶段算账,Commit 阶段交付

state 更新 / props 更新 / context 更新↓
---- Render 阶段(可中断) ----
1. 执行组件函数
2. 运行 hooks
3. 生成新的 Fiber 树
4. 计算 diff
5. 构建 effectList(DOM 变更清单)↓
---- Commit 阶段(不可中断) ----
1. before mutation(DOM 操作前的准备)
2. mutation(真实 DOM 更新)
3. layout(执行 useLayoutEffect、componentDidMount)↓
浏览器绘制(paint)↓
最后执行 useEffect(异步)

五、Fiber 是如何实现“可中断”的?

核心思想:时间切片(Time Slicing)

React 不再:

renderTree(); // 一口气干完

而是:

while (还有时间 && 还有任务) {执行一个 Fiber
}

如果:

  • 浏览器要绘制
  • 用户输入
  • 高优先级任务来了

那么,React 暂停当前 Fiber,稍后恢复。

Fiber 为什么能恢复?

因为 Fiber 本身就保存了:

  • 执行到哪了
  • 子节点处理到哪
  • 副作用信息

六、优先级调度(Scheduler)

不同更新优先级不同:

React 可以:

  • 丢弃低优先级渲染
  • 重做高优先级渲染
  • 但 UI 不会乱

七、一次 setState 的 Fiber 流程

setCount(c => c + 1);

内部流程:

  1. 创建 update
  2. 挂到 Fiber.updateQueue
  3. 根据优先级调度
  4. 创建 workInProgress Fiber
  5. render 阶段计算新 state(state 永远只在 Fiber 上变)
  6. 标记 flags
  7. commit 阶段更新 DOM

八、和 Vue 响应式的根本差异

Vue:数据驱动更新 React:调度驱动更新

Vue:

state.x = 1 → 精确更新

React:

setState → 重新执行组件

Fiber 的存在,是 React 能做到并发的前提。

九、如何实现“并发”?

React 并发(Concurrent)不是多线程,而是:在单线程 JS 中,把一次渲染拆成可中断、可重试、可丢弃的任务调度模型。

⚠️ React 并发 ≠ Promise ≠ async/await ≠ Web Worker

并发的是 “渲染任务的调度权”,React 可以在多个“未完成的渲染版本”之间来回切换。

本质上就是通过 双 Fiber 树 + render/commit 分离 + scheduler 调度器 ​实现的。

并发特性​是否生效​,取决于:

  • useTransition
  • useDeferredValue
  • Suspense
  • 更新优先级

scheduler 调度器 体现在开发层面是指 useTransition、useDeferredValue、Suspense 等。

这些都是并发

1️⃣ 可中断(Interruptible)

渲染到一半 →浏览器要绘制 →React 暂停 render

2️⃣ 可重试(Restartable)

低优先级渲染中 →高优先级更新来了 →丢弃当前渲染 →从头再算

3️⃣ 可丢弃(Discardable)

用户连续输入 →前面几次渲染直接废弃

最终只 commit“最后一次正确结果”

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询