标准答案
- key 用来标识列表中每一项的稳定身份。Vue diff 列表时,会根据 key 判断哪些节点可以复用、哪些需要移动、创建或卸载。
- 稳定 key 通常来自业务唯一 id,例如 user.id、product.id、record.id。
- 没有 key 或使用不稳定 key 时,Vue 可能按位置复用节点。列表插入、删除、排序后,输入框内容、组件内部状态、动画状态可能落到错误项目上。
- index 只有在列表静态、不排序、不插入删除、不保存子组件状态时才勉强可用。动态列表不应该用 index 当 key。
- key 不是为了消除警告而随便加一个随机值。每次渲染都变化的随机 key 会让 Vue 每次都销毁重建节点,反而损失性能和状态。
题目解析
key 的本质是节点身份,不是数组下标。数组下标描述当前位置,业务 id 描述这一项是谁。
列表 diff 会尽量复用已有 DOM 和组件实例。稳定 key 能让复用发生在正确的项目上。
在表单列表、拖拽排序、动画列表和带内部状态的子组件里,错误 key 的影响最明显。
代码示例
这个例子里,使用 todo.id 能让输入状态和具体任务保持绑定。
Vue
<script setup lang="ts">
const todos = [
{ id: 'todo-1', title: '准备简历' },
{ id: 'todo-2', title: '复习 Vue' }
]
</script>
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
<input :value="todo.title">
</li>
</ul>
</template>常见误区
- 动态列表使用 index 当 key,插入或删除后组件状态错位。
- 使用 Math.random() 或 Date.now() 当 key,导致每次渲染都重新创建节点。
- 认为 key 只影响性能。key 更重要的是影响节点和组件实例的身份匹配。