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
的效果基本相同。
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
当你使用 <template v-for>
时,key
应该被放置在这个 <template>
容器上:
<template v-for="todo in todos" :key="todo.name">
<li>{{ todo.name }}</li>
</template>
总结
- 唯一标记:
key
为每个虚拟节点(vnode
)提供了一个唯一的标识符。这个唯一标识符使得Vue
在进行Diff
(差异)操作时能够更准确、更快速地更新虚拟DOM
。例如,当使用v-for
时,key
可以帮助Vue
正确地识别和复用已渲染过的元素,即使数据项的顺序发生变化 - 数据绑定:在某些情况下,如
v-if
或v-for
中使用key
,可以防止Vue
尝试就地复用元素。例如,在v-if
中使用key
可以确保即使条件变化导致模板被隐藏,也不会清除用户已输入的内容。在v-for
中使用key
可以防止Vue
尝试就地复用元素,确保每个元素都有唯一的标识符。 key
还可以用于强制替换元素或组件,而不是重复使用它们。在某些情况下,如使用相同标签名的元素进行过渡切换时,key
有助于Vue
区分这些元素