react diff算法实现
React Diff 算法实现原理
React 的 Diff 算法(Reconciliation)是虚拟 DOM(Virtual DOM)更新的核心机制,通过高效比较新旧虚拟 DOM 树的差异,最小化真实 DOM 操作。以下是其关键实现原理:
同级比较(Tree Diff)
React 采用分层比较策略,仅对同一层级的节点进行对比。若节点跨层级移动(如从第 2 层移动到第 3 层),React 会直接销毁旧节点并重建新节点,而非跨层级追踪变化。这种策略将算法复杂度从 O(n³) 降低到 O(n)。
组件类型比较(Component Diff)
若组件类型不同(如从 <Button> 变为 <Div>),React 会直接卸载旧组件及其子树,并挂载新组件。对于相同类型的组件,React 会递归比较其子节点。

列表节点的 Key 优化(Element Diff)
列表节点(如动态渲染的数组元素)通过唯一 key 标识优化比对。React 会优先复用 key 相同的节点,减少不必要的销毁和重建。若无 key,列表顺序变化可能导致性能下降。
核心实现步骤
虚拟 DOM 节点比对
React 通过 ReactElement 对象描述虚拟 DOM 节点。Diff 时比较以下属性:

type:节点类型(如'div'或自定义组件)。props:节点属性(包括children)。key:列表节点的唯一标识。
递归协调过程
- 根节点比对:若根节点类型不同,直接替换整棵树。
- 属性更新:若节点类型相同,更新变化的属性(如
className、style)。 - 子节点递归:对子节点列表进行逐层比对,优先匹配
key相同的节点。
列表 Diff 的优化策略
React 使用“双指针”算法优化列表比对:
- 新旧列表的头尾节点对比,跳过未变化的节点。
- 若无匹配的
key,将新节点插入到旧列表的对应位置。
代码示例
以下是一个简化的 Diff 算法伪代码逻辑:
function reconcileChildren(parentNode, oldChildren, newChildren) {
let oldIndex = 0;
let newIndex = 0;
const lastIndex = oldChildren.length - 1;
while (newIndex < newChildren.length) {
const oldChild = oldChildren[oldIndex];
const newChild = newChildren[newIndex];
if (areKeysEqual(oldChild, newChild)) {
// 复用节点并更新属性
updateNode(oldChild, newChild);
oldIndex++;
newIndex++;
} else {
// 查找可复用的旧节点
const reusedIndex = findKeyIndex(oldChildren, newChild.key);
if (reusedIndex >= 0) {
// 移动节点到新位置
moveNode(parentNode, oldChildren[reusedIndex], newIndex);
oldIndex++;
} else {
// 插入新节点
insertNode(parentNode, newChild, newIndex);
}
newIndex++;
}
}
// 移除旧列表中未使用的节点
while (oldIndex <= lastIndex) {
removeNode(parentNode, oldChildren[oldIndex]);
oldIndex++;
}
}
性能优化建议
- 稳定的 Key:列表项使用唯一且稳定的
key(如数据 ID),避免随机数或索引。 - 避免深层嵌套:减少不必要的组件层级,降低递归深度。
- 使用
React.memo:对静态组件进行记忆化,避免重复 Diff。
通过上述策略,React 能够在保证性能的前提下,高效更新用户界面。






