第 3 周:Fiber 架构原理(调和流程)

目标:

  • 理解 beginWork、completeWork 的作用

  • 搞懂调和的核心流程

推荐文件:

  • ReactFiberBeginWork.js

  • ReactFiberCompleteWork.js

  • ReactChildFiber.js

 理解 beginWork、completeWork 的作用

 在 React 源码中,beginWorkcompleteWork调和(reconciliation)阶段的核心函数,它们构成了 Fiber 工作流程的前后两步,分别处理「开始」和「完成」的逻辑。

总体理解

React 构建 Fiber 树(工作单元)的过程是通过一个 “双缓冲 Fiber 架构” 来实现的:

  • beginWork:创建/更新子 Fiber 节点 ——「拆分工作单元

  • completeWork:根据子节点完成当前节点 ——「归并工作结果

你可以类比为:

beginWork:我需要干什么?
completeWork:我已经干完了,汇总下结果。

🔍 一、beginWork:从上往下,调和子节点

function beginWork(current, workInProgress, renderLanes): Fiber | null
  • current 是旧的 Fiber 节点(可能是 null)

  • workInProgress 是正在构建的新 Fiber 节点

  • 它会:

    • 根据 workInProgresstype(函数组件、类组件、DOM 节点等)

    • 调用对应的更新函数(如 updateFunctionComponent, updateHostComponent 等)

    • 创建并返回它的第一个子节点(继续下一轮 beginWork)

📌 关键职责

  • 比较 props 是否变化,决定是否跳过更新

  • 根据组件类型,处理 state、effect

  • 创建子 Fiber(reconcileChildren

🛠 例子:

function updateFunctionComponent(...) {
  const children = renderWithHooks(...)  // 执行函数组件逻辑
  reconcileChildren(...)                 // 生成子 fiber 链表
  return workInProgress.child            // 进入下一个 beginWork
}

 

🔄 二、completeWork:从下往上,生成副作用/最终输出

function completeWork(current, workInProgress, renderLanes)
  • beginWork 相对,从 子节点回到父节点

  • 汇总信息,比如:

    • 生成 DOM 节点(createInstance

    • 记录副作用(flags: Placement/Update/Deletion)

    • 设置 stateNode

    • 绑定 DOM 属性等

📌 关键职责

  • 创建/更新 DOM(或其他宿主环境节点)

  • 链接兄弟节点

  • 收集副作用(flags)

🛠 例子:

function completeWork(current, workInProgress) {
  switch (workInProgress.tag) {
    case HostComponent:
      if (!current) {
        // 首次挂载,创建 DOM 节点
        const instance = createInstance(...)
        appendAllChildren(instance, workInProgress)
        workInProgress.stateNode = instance
      }
      break
  }
}

🧭 三、beginWork 与 completeWork 的配合流程(深度优先)

调和过程是 DFS 的:

beginWork(A)
  beginWork(B)
    beginWork(C)
    completeWork(C)
  completeWork(B)
completeWork(A)

这就是为啥你会看到 React 的调和是“从父到子,再从子归并到父”。

阶段函数名作用类比
开始(向下)beginWork调和子节点,生成子 Fiber分解任务
完成(向上)completeWork汇总子节点结果,创建 DOM 或收集副作用任务收尾

✅ 你在源码中如何追踪?

  • performUnitOfWork 开始:

function performUnitOfWork(unitOfWork: Fiber) {
  const next = beginWork(current, unitOfWork, renderLanes)
  ...
  if (!next) completeUnitOfWork(unitOfWork)
}
 如何本地调试代码

react版本列表

下载一个react的版本,我用的是18.3.0的版本,然后使用node16,执行了yarn install,安装了依赖,然后执行下面的打包命令,不要用最新的19版本,打包后的文件目录不同了

# 执行打包命令
yarn build react/index,react/jsx,react-dom/index,scheduler --type=NODE

 

现在源码目录build/node_modules下会生成最新代码的包。我们为reactreact-dom创建yarn link

通过yarn link可以改变项目中依赖包的目录指向

cd build/node_modules/react
# 申明react指向
yarn link
cd build/node_modules/react-dom
# 申明react-dom指向
yarn link

 接下来我们通过create-react-app在其他地方创建新项目。这里我们随意起名,比如“react-test”。

npx create-react-app react-test

 在新项目中,将reactreact-dom2个包指向react18.3.0下我们刚才生成的包。

# 将项目内的react react-dom指向之前申明的包
yarn link react react-dom

现在试试在react/build/node_modules/react-dom/cjs/react-dom.development.js中随意打印些东西。

react-test项目下执行yarn start。现在浏览器控制台已经可以打印出我们输入的东西了。

搞懂调和的核心流程 

一句话理解调和(Reconciliation)

调和是 React 在更新阶段用 Fiber 树对比新旧 Virtual DOM,并计算出最小变更的过程,最终生成“Effect List”供 commit 阶段使用。

学习调和核心流程的完整路径

🥇 第一步:理解 Fiber 架构的核心概念

概念说明
Fiber 节点包含组件信息的工作单元,代替以前的 Virtual DOM
Work Loop整个调和阶段的遍历引擎,按时间分片、可中断
beginWork每个 Fiber 的“构建”阶段:计算子节点
completeWork每个 Fiber 的“收尾”阶段:生成 DOM 或 effect
Effect List记录需要执行副作用的 Fiber 链表,提交阶段用
commitWork真正执行副作用,比如操作 DOM、调用生命周期等

第二步:亲手调试源码

推荐调试入口是 ReactDOMServer.renderToString(),触发构建 Fiber 树并走完整个调和流程。

推荐打断点的文件:

  • ReactFiberWorkLoop.new.js:调和主循环 workLoopSync

  • ReactFiberBeginWork.new.jsbeginWork 逻辑

  • ReactFiberCompleteWork.new.jscompleteWork 逻辑

  • ReactChildFiber.jsreconcileChildren 是调和的核心函数之一

  • ReactFiberReconciler.js:暴露外部接口,如 createContainerupdateContainer

 第三步:自己写一个极简调和器(mini reconciler)

function beginWork(fiber) {
  if (typeof fiber.type === 'function') {
    fiber.child = fiber.type(fiber.props);
  } else {
    fiber.stateNode = createDom(fiber);
  }
  return fiber.child;
}

function completeWork(fiber) {
  if (fiber.return) {
    fiber.return.effects = fiber.return.effects || [];
    fiber.return.effects.push(fiber);
  }
}

function workLoop(rootFiber) {
  let next = rootFiber;
  while (next) {
    let child = beginWork(next);
    if (child) {
      next = child;
    } else {
      while (next) {
        completeWork(next);
        if (next.sibling) {
          next = next.sibling;
          break;
        }
        next = next.return;
      }
    }
  }
}

 

总结你该掌握的关键流程

  1. 从 React 元素(JSX)转成 Fiber 节点

  2. 通过 beginWork 构建子 Fiber(递)

  3. 通过 completeWork 完成当前 Fiber(归)

  4. 收集 effect 到 EffectList

  5. commitWork 真正执行 DOM 操作

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值