joken-前端工程师

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
  404 随笔 :: 39 文章 :: 8 评论 :: 20万 阅读

以下是 React 同层级比较算法(即 Diff 算法中“只比较同级”的部分)的简洁总结,涵盖其核心原理、规则和关键点:


React 同层级比较算法总结

定义

React 的 Diff 算法通过只比较同层级节点的方式,高效对比新旧虚拟 DOM(VDOM)树,找出变化部分并更新真实 DOM。这是 Fiber 架构下协调(Reconciliation)过程的核心步骤。

核心原理

  • 限制比较范围:只在同一层级对比新旧节点,不跨层级匹配。
  • 类型决定命运:节点类型(标签、组件)是比较的首要依据。
  • 细粒度更新:尽量复用节点,只更新变化部分,避免全替换。

比较规则

  1. 类型不同
    • 如果新旧节点的类型不同(如 <div> vs <span> 或不同组件):
      • 删除旧节点及其整个子树。
      • 创建并插入新节点及其子树。
    • 结果:整个节点及其子节点被替换。
  2. 类型相同
    • 如果新旧节点类型相同:
      1. 比较属性(props)
        • 检查 props(如 classNamestyle),只更新变化的属性。
      2. 递归子节点
        • 对子节点继续执行同层级比较,而不是直接替换。
    • 结果:节点复用,属性和子节点按需更新。
  3. 列表比较
    • 无 key:按索引顺序逐个比较,类型不同替换,类型相同深入比较。
    • 有 key
      • 使用 key 匹配新旧节点:
        • 匹配成功:复用节点,深入比较。
        • 未匹配:旧节点删除,新节点插入。
      • 支持节点移动(如顺序变化),优化性能。

示例

  1. 类型不同
    // 旧:<div>Text</div>
    // 新:<span>Text</span>
    
    • 类型不同,删除 <div>,插入 <span>,子节点 Text 不保留。
  2. 类型相同
    // 旧:<div className="old">Text</div>
    // 新:<div className="new">Text</div>
    
    • 类型相同,更新 className,子节点 Text 复用。
  3. 列表比较
    // 旧:<ul><li key="a">A</li><li key="b">B</li></ul>
    // 新:<ul><li key="b">B</li><li key="c">C</li></ul>
    
    • key="b" 匹配,复用;key="a" 删除,key="c" 插入。

优化策略

  • Key 匹配:通过 key 快速定位列表中的相同节点,降低复杂度从 O(n³) 到 O(n)。
  • 跳过跨层:不尝试匹配跨层级节点,简化算法(假设跨层移动罕见)。

时间复杂度

  • 单节点:O(1),仅比较类型和属性。
  • 列表无 key:O(n³)(理论上,但不实际使用)。
  • 列表有 key:O(n),通过 key 快速匹配。

Fiber 架构支持

  • 载体:每个节点是 Fiber 对象,存储类型、props 和子节点关系。
  • 可中断:同层级比较可以分片执行,支持暂停和恢复。

优点与局限

  • 优点
    • 高效:限制比较范围,减少不必要操作。
    • 复用:类型相同节点可保留,避免全替换。
  • 局限
    • 跨层级移动视为删除+新增,无法优化。

一句话总结

React 同层级比较算法通过只对比同一层级节点,根据类型决定替换或复用,并借助 key 优化列表更新,在 Fiber 架构下实现高效、可中断的 DOM diff。


这个总结提炼了算法的本质,如果你需要更具体的代码实现或某个场景的分析,可以告诉我!

posted on   joken1310  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示