前端面试宝典

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 算法的核心策略(面试常考)

  1. 先比较 key
    key 不同直接跳过,不继续对比子元素和内容,性能极高。

  2. key 相同,再比较元素类型
    都是 li → 复用。
    一个 li,一个 div → 重建。

  3. 最后比较内容/子节点
    只更新变化的文本、属性。


六、最重要的结论(背会就够用)

  1. 虚拟 DOM:用 JS 对象模拟 DOM,避免频繁操作真实 DOM。
  2. Diff 算法:对比新旧虚拟 DOM,最小量更新真实 DOM
  3. key 的作用:给 Diff 算法提供唯一标识,让它精准判断节点。
  4. 严禁 index 做 key:列表增删、排序时,节点复用错误 → 数据错乱
  5. 最佳实践:key 使用唯一 id(id / uuid)。

一句话终极总结

虚拟 DOM 负责轻量描述页面,Diff 算法依靠 key 精准对比新旧节点,最终只更新必要的真实 DOM。

你如果需要,我还能给你画一张 虚拟 DOM Diff 流程图,一眼看懂整个过程!