简化 Fiber 遍历算法

理解 Fiber 遍历算法 ------ 用代码和图示讲清「深度优先遍历」

在 React 的 Fiber 架构中,更新和调度的本质就是遍历链状结构「Fiber 树」。下面通过一个简化 TypeScript 例子,梳理 Fiber 遍历的过程与背后的逻辑。


Fiber 节点的数据结构

每个 Fiber 节点除了「类型」外,用 child、sibling、parent 指针构建了一个多叉树:

typescript 复制代码
class Fiber {
    type: string
    child: Fiber | null
    sibling: Fiber | null
    parent: Fiber | null
    constructor(type: string) {
        this.type = type
        this.child = null
        this.sibling = null
        this.parent = null
    }
}
  • child 指向第一个子节点
  • sibling 指向右边的兄弟节点
  • parent 指向父节点

通过这三根指针组成了一颗可以自底向上(parent)、自右向左(sibling)、自上向下(child)遍历的数据结构。


关键:performUnitOfWork 的遍历实现

核心函数 performUnitOfWork 做了两件事:

  1. 执行当前节点的工作 (示例中用 console.log)
  2. 决定下一个要遍历的 Fiber 节点 ------ 按照"先子节点后兄弟节点,否则回溯父节点"的顺序

代码如下:

typescript 复制代码
const performUnitOfWork = (fiber: Fiber) => {
    console.log(fiber.type) // 模拟执行Fiber工作
    if (fiber.child) {
        return fiber.child      // 优先遍历子节点
    }

    // 没有child,就找下一个sibling,没有sibling向上回溯parent
    let next: Fiber | null = fiber
    while (next) {
        if (next.sibling) {
            return next.sibling
        }
        next = next.parent
    }
    // 如果没有父级也没有兄弟,说明遍历完毕,返回undefined
}

实际上这是一个典型「深度优先遍历」(DFS, Depth-First Search):

  1. 优先访问 child
  2. child 为空则访问下一个 sibling
  3. sibling 也为空则不断回溯 parent,直到找到上级的 sibling
  4. parent 也没有 sibling,遍历结束

这种遍历方式可以保证逐步深入 Fiber 树,且每个节点都只访问一遍。


优化版 Fiber 树结构与遍历顺序演示

为了更好地说明深度优先遍历过程,我们设计如下更具代表性的 Fiber 树结构,包含了父-子、兄弟多层关系:

typescript 复制代码
let root = new Fiber("root")
let A = new Fiber("A")
let B = new Fiber("B")
let C = new Fiber("C")
let A1 = new Fiber("A1")
let A2 = new Fiber("A2")
let B1 = new Fiber("B1")
let C1 = new Fiber("C1")
let C2 = new Fiber("C2")

root.child = A
A.parent = root
A.sibling = B
B.parent = root
B.sibling = C
C.parent = root

A.child = A1
A1.parent = A
A1.sibling = A2
A2.parent = A

B.child = B1
B1.parent = B

C.child = C1
C1.parent = C
C1.sibling = C2
C2.parent = C

对应的树状结构如下(缩进代表层级关系):

css 复制代码
root
 ├─ A
 │   ├─ A1
 │   └─ A2
 ├─ B
 │   └─ B1
 └─ C
     ├─ C1
     └─ C2
  • child 指向第一个子节点
  • 通过 sibling 串起同级兄弟

深度优先遍历过程中,每次优先 child,然后是 sibling,最后回溯 parent 的 sibling,直到结束。用如下流程图可视化遍历顺序:

该遍历顺序为:root → A → A1 → A2 → B → B1 → C → C1 → C2


遍历入口

Traversal 的入口代码与之前一致:

typescript 复制代码
let current: Fiber | undefined = root
while (current) {
    current = performUnitOfWork(current)
}
  • 每次调用 performUnitOfWork,返回下一个待遍历节点
  • 返回 undefined 时跳出循环,遍历结束

总结

通过这种「优先 child、再寻找 sibling、最后回溯 parent」的深度优先遍历,Fiber 树能够在可中断(分片)的情况下高效、稳定地调度更新。这也是 React Fiber 架构用以实现异步可中断渲染的底层基础。

相关推荐
FungLeo4 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
Csvn5 小时前
并发模式:让渲染学会排队、插队和让路
前端
可乐鸡翅yeah_6 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
Flynt6 小时前
Linear 用 1000 个 PR 换掉 styled-components,我写了 200 个按钮,把这笔账复现了一遍
前端·css·preact
JavaGuide7 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel7 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘8 小时前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马8 小时前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut8 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia1239 小时前
实现完整 Tool Dispatcher
开发语言·前端