Skip to content

key 的作用和工作原理

提示

key 这个特殊的 attribute 主要作为 Vue 的虚拟 DOM 算法提示,在比较新旧节点列表时用于识别 vnode

在没有 key 的情况下,Vue 将使用一种最小化元素移动的算法,并尽可能地就地更新/复用相同类型的元素。如果传了 key,则将根据 key 的变化顺序来重新排列元素,并且将始终移除/销毁 key 已经不存在的元素。

同一个父元素下的子元素必须具有唯一的 key。重复的 key 将会导致渲染异常。

描述

首先是官方文档的描述,当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用就地更新的策略,如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态的列表渲染输出,例如表单输入值。为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute,建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

简单来说,当在列表循环中使用 key 时,需要使用 key 来给每个节点做一个唯一标识,diff 算法就可以正确的识别此节点,找到正确的位置直接操作节点,尽可能地进行重用元素,key 的作用主要是为了高效的更新虚拟 DOM。此外,使用 index 作为 key 是并不推荐的做法,其只能保证 Vue 在数据变化时强制更新组件,以避免原地复用带来的副作用,但不能保证最大限度的元素重用,且使用 index 作为 key 在数据更新方面和不使用 key 的效果基本相同。

vue
<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

当你使用 <template v-for> 时,key 应该被放置在这个 <template> 容器上:

vue
<template v-for="todo in todos" :key="todo.name">
  <li>{{ todo.name }}</li>
</template>

总结

  1. 唯一标记key为每个虚拟节点(vnode)提供了一个唯一的标识符。这个唯一标识符使得 Vue 在进行 Diff(差异)操作时能够更准确、更快速地更新虚拟 DOM。例如,当使用v-for时,key可以帮助 Vue 正确地识别和复用已渲染过的元素,即使数据项的顺序发生变化
  2. 数据绑定:在某些情况下,如v-ifv-for中使用key,可以防止 Vue 尝试就地复用元素。例如,在v-if中使用key可以确保即使条件变化导致模板被隐藏,也不会清除用户已输入的内容。在v-for中使用key可以防止 Vue尝试就地复用元素,确保每个元素都有唯一的标识符。
  3. key还可以用于强制替换元素或组件,而不是重复使用它们。在某些情况下,如使用相同标签名的元素进行过渡切换时,key有助于 Vue 区分这些元素