Vue 虚拟 DOM + Diff 算法 超通俗讲解(结合上一章的 key 案例)
我用最简单、最直白、不绕弯的方式,把 Vue 最核心的虚拟 DOM + Diff 算法一次性讲透,你看完就能彻底理解。
一、先搞懂 3 个基础概念
1. 真实 DOM
浏览器渲染的页面元素,操作它极慢、极耗性能(修改一次就重排/重绘)。
2. 虚拟 DOM(VDOM)
用JS 对象模拟页面结构,轻量、超快。
比如:
// 虚拟DOM 就是个简单对象
const vdom = {
tag: 'ul',
children: [
{ tag: 'li', key: 001, text: '张三' }
]
}
3. Diff 算法
数据变化 → 生成新虚拟 DOM → 和旧虚拟 DOM 对比 → 找出差异 → 只更新变化的真实 DOM
👉 一句话总结 Diff 算法:最小量更新真实 DOM,提升性能。
二、Diff 算法的核心规则(必背)
Vue 的 Diff 算法遵循两个最关键原则:
1. 同层比较,绝不跨层
只对比同一层级的节点,不跨父子、跨兄弟对比,速度极快。
2. key 是判断节点是否相同的唯一依据
- key 相同 → 认为是同一个节点 → 复用 DOM,就地更新
- key 不同 → 认为是不同节点 → 销毁旧 DOM,创建新 DOM
这就是你刚才 key=index 出 Bug 的根本原因!
三、Diff 算法执行流程(超清晰)
当数据改变时,Vue 会做这 4 步:
第 1 步:数据更新
比如你执行 persons.unshift(老刘)
第 2 步:生成 新虚拟DOM
Vue 根据新数据,生成一棵新 VDOM 树
第 3 步:新旧虚拟 DOM 开始 Diff 对比
按 key 一一匹配:
- 找到相同 key → 复用节点,只更新内容
- 找不到相同 key → 删掉旧的,创建新的
第 4 步:将差异打补丁到真实 DOM
只改变化的部分,不重新渲染整个列表。
四、结合你的代码:为什么 key=index 会错乱?
旧列表 key = index
key=0 → 张三
key=1 → 李四
key=2 → 王五
头部插入老刘后
key=0 → 老刘
key=1 → 张三
key=2 → 李四
key=3 → 王五
Diff 算法判断:
- key=0 还在 → 复用 DOM(把张三文字改成老刘,但输入框不动)
- key=1 还在 → 复用 DOM
- key=2 还在 → 复用 DOM
- key=3 新增 → 新建 DOM
结果:输入框和数据错位!
如果用唯一 id 做 key
key:001 → 张三
key:002 → 李四
key:003 → 王五
插入老刘后:
key:004 → 老刘
key:001 → 张三
key:002 → 李四
key:003 → 王五
Diff 算法判断:
- 001、002、003 都还在 → 完整复用 DOM
- 004 是新的 → 只在最前面创建新 DOM
结果:数据和输入框完全对应!
五、Diff 算法的核心策略(面试常考)
-
先比较 key
key 不同直接跳过,不继续对比子元素和内容,性能极高。 -
key 相同,再比较元素类型
都是 li → 复用。
一个 li,一个 div → 重建。 -
最后比较内容/子节点
只更新变化的文本、属性。
六、最重要的结论(背会就够用)
- 虚拟 DOM:用 JS 对象模拟 DOM,避免频繁操作真实 DOM。
- Diff 算法:对比新旧虚拟 DOM,最小量更新真实 DOM。
- key 的作用:给 Diff 算法提供唯一标识,让它精准判断节点。
- 严禁 index 做 key:列表增删、排序时,节点复用错误 → 数据错乱。
- 最佳实践:key 使用唯一 id(id / uuid)。
一句话终极总结
虚拟 DOM 负责轻量描述页面,Diff 算法依靠 key 精准对比新旧节点,最终只更新必要的真实 DOM。
你如果需要,我还能给你画一张 虚拟 DOM Diff 流程图,一眼看懂整个过程!