以下是 React 同层级比较算法(即 Diff 算法中“只比较同级”的部分)的简洁总结,涵盖其核心原理、规则和关键点:
React 同层级比较算法总结
定义
React 的 Diff 算法通过只比较同层级节点的方式,高效对比新旧虚拟 DOM(VDOM)树,找出变化部分并更新真实 DOM。这是 Fiber 架构下协调(Reconciliation)过程的核心步骤。
核心原理
- 限制比较范围:只在同一层级对比新旧节点,不跨层级匹配。
- 类型决定命运:节点类型(标签、组件)是比较的首要依据。
- 细粒度更新:尽量复用节点,只更新变化部分,避免全替换。
比较规则
- 类型不同:
- 如果新旧节点的类型不同(如
<div>
vs<span>
或不同组件):- 删除旧节点及其整个子树。
- 创建并插入新节点及其子树。
- 结果:整个节点及其子节点被替换。
- 如果新旧节点的类型不同(如
- 类型相同:
- 如果新旧节点类型相同:
- 比较属性(props):
- 检查 props(如
className
、style
),只更新变化的属性。
- 检查 props(如
- 递归子节点:
- 对子节点继续执行同层级比较,而不是直接替换。
- 比较属性(props):
- 结果:节点复用,属性和子节点按需更新。
- 如果新旧节点类型相同:
- 列表比较:
- 无 key:按索引顺序逐个比较,类型不同替换,类型相同深入比较。
- 有 key:
- 使用
key
匹配新旧节点:- 匹配成功:复用节点,深入比较。
- 未匹配:旧节点删除,新节点插入。
- 支持节点移动(如顺序变化),优化性能。
- 使用
示例
- 类型不同:
// 旧:<div>Text</div> // 新:<span>Text</span>
- 类型不同,删除
<div>
,插入<span>
,子节点Text
不保留。
- 类型不同,删除
- 类型相同:
// 旧:<div className="old">Text</div> // 新:<div className="new">Text</div>
- 类型相同,更新
className
,子节点Text
复用。
- 类型相同,更新
- 列表比较:
// 旧:<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。
这个总结提炼了算法的本质,如果你需要更具体的代码实现或某个场景的分析,可以告诉我!
前端工程师、程序员
标签:
react18
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~