React19.x 一个示例来看 Diff 算法

setStatescheduleUpdateOnFiberrender 阶段(包含 beginWorkreconcileChildren ← Diff 发生处 → completeWork → commit 阶段 → DOM mutation。

第一轮遍历(从左到右快速匹配,复杂度 O(n)): 同时遍历新旧节点数组,尽可能复用 key 和 type 都相同的前缀节点。如果遇到 key 相同但 type 不同的情况,React 会直接丢弃旧节点并基于新的 React Element 生成全新 Fiber(旧节点放入 deletions 数组待删除),但遍历并不会终止------这说明 React 对待"key 相同、类型变了"的策略是继续往后尝试匹配。如果遇到 key 和 type 都不相同的情况,则立即结束遍历。

第二轮遍历(处理边界):

  • 情况一 :旧节点有剩余,新节点已遍历完 → 将剩余旧节点标记为 Deletion
  • 情况二:新节点有剩余,旧节点已遍历完 → 为剩余新节点创建新的 Fiber;

第三轮遍历(处理剩余节点): 如果第二轮结束后还有新旧节点未被处理,进入第三轮:

两者都有剩余 → 将剩余旧节点按 key 放入 Map,然后遍历剩余新节点,从 Map 中寻找可复用的节点。在这轮遍历中,React 通过维护 lastPlacedIndex(上一个未移动节点在旧数组中的最大索引)来判断节点是否需要移动。

示例

js 复制代码
import { useState } from 'react';

const RenderArray = () => {
  const [array, setArray] = useState<string[]>(['A','B','C','D','E']);

  return (
    <div key="render-array">
      <h1>RenderArray</h1>
      <button onClick={() => setArray(['A','B','E','D','C','F'])}>Set Array</button>
      <ul>
        {array.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
};
export default RenderArray;

reconcileChildrenArray

阶段 1:第一轮遍历(同步遍历新旧节点,快速复用同位置节点)

1、A节点

updateSlot 复用节点

updateElement

placeChild。负责确定新 Fiber 节点在 Fiber 树中的位置,并根据情况标记该节点是需要移动、插入还是保持原位,同时返回更新后的 lastPlacedIndex 值。

A 节点,不需要移动。

2、B节点 与A 节点一样的逻辑

3、新节点 E 、旧节点 C,两者 不同

退出当前第一阶段

阶段 2:处理边界情况(旧节点耗尽 或 新节点遍历完)

情况 2.1:新节点遍历完(newIdx === newChildren.length)

情况 2.2:旧节点遍历完(oldFiber === null)

当前情节跳过,进入第三阶段。

阶段 3:第三轮遍历(键映射表复用 + 计算节点移动)

步骤1:构建剩余旧节点的键映射表(key → Fiber)

步骤2:遍历剩余的新节点,从映射表中查找可复用节点

1、E节点, 找到复用。

不移动

2、找到 D 节点,复用,需要移动

3、找到 C节点,复用,需要移动

4、F节点,新节点,标记插入

创建新节点 createFiberFromElement

标记插入

步骤3:标记删除映射表中剩余的旧节点(无新节点匹配)

相关推荐
zithern_juejin13 小时前
手写instanceof
javascript
ZengLiangYi13 小时前
MCP 协议从零实现:手写最简 MCP Server
前端·javascript·后端
yspwf13 小时前
Node.js 本地下载并使用 Hugging Face 中文向量模型:以 bge-base-zh-v1.5 为例
javascript·后端
小救星小杜、13 小时前
new Router base的作用
前端·javascript·vue.js
cvcode_study13 小时前
Electron 制作自定义浏览器
前端·javascript·electron
z落落13 小时前
C# 数组高阶函数(Find/FindAll/Exists/ForEach/All/Any)
javascript·数据结构·算法
之歆13 小时前
Day20_PC 端电商商品详情页前端实战:从布局到放大镜与选项卡
开发语言·前端·javascript·css·less
ct97813 小时前
Object.defineProperty/Proxy与 vue2 + vue3 响应式原理
前端·javascript·vue.js
存在的五月雨13 小时前
Vue中的nextTick
javascript·vue.js·ecmascript