Vue 中 key 的作用
key 是 Vue 的一个特殊 attribute,主要用于 Vue 的虚拟 DOM 算法,在新旧节点对比(Diff 算法)时辨识 VNodes。
1. 核心作用:Diff 算法的标识
在没有 key 的情况下,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法(就地更新策略)。
而当使用了 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除/销毁 key 不存在的元素。
场景 1:v-for 列表渲染 (最常见)
vue
<ul>
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</ul>- 为什么要用 ID 而不是 Index? 如果使用 index 作为 key,当列表顺序发生变化(如在头部插入一项)时,index 会发生错位。Vue 会认为旧的 index 0 变成了新的 index 0(实际上内容变了),导致就地复用,这可能会引发以下问题:
- 性能损耗:虽然 DOM 节点复用了,但内容要全部更新。
- 状态错乱:如果列表项中有
<input>或子组件维持了内部状态,状态会保留在原来的 index 位置,导致数据和 UI 不匹配。
场景 2:强制替换元素/组件
如果你想强制触发生命周期钩子,或者触发过渡动画,可以改变 key。
vue
<!-- 当 text 变化时,<span> 会被销毁并重新创建 -->
<!-- 这会触发进入/离开的过渡动画 -->
<transition>
<span :key="text">{{ text }}</span>
</transition>vue
<!-- 当 id 变化时,Component 会被销毁并重新创建 -->
<!-- 完整的生命周期钩子(created, mounted 等)会重新执行 -->
<Component :key="id" />2. 原理简述
在 Diff 算法中,Vue 会通过 key 生成一个 Map 映射。
- 无 key:O(n) 遍历查找,或直接就地复用(可能出错)。
- 有 key:O(1) 直接通过 Map 找到对应的旧节点。
3. 总结
- 准确性:避免就地复用带来的状态 bug(特别是在表单输入、组件状态场景)。
- 性能:帮助 Diff 算法更快地找到对应的节点,减少不必要的 DOM 操作(虽然创建销毁有开销,但相比错误的 DOM 更新,逻辑更正确)。
- 功能:用于强制触发生命周期或动画。
最佳实践:在
v-for中始终使用唯一 ID 作为 key,尽量避免使用 index。