标准答案

  1. key 用来标识列表中每一项的稳定身份。Vue diff 列表时,会根据 key 判断哪些节点可以复用、哪些需要移动、创建或卸载。
  2. 稳定 key 通常来自业务唯一 id,例如 user.id、product.id、record.id。
  3. 没有 key 或使用不稳定 key 时,Vue 可能按位置复用节点。列表插入、删除、排序后,输入框内容、组件内部状态、动画状态可能落到错误项目上。
  4. index 只有在列表静态、不排序、不插入删除、不保存子组件状态时才勉强可用。动态列表不应该用 index 当 key。
  5. 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 更重要的是影响节点和组件实例的身份匹配。

作者信息