新手必知!Vue 里 key 的底层逻辑(超通俗讲解)

145 阅读2分钟

咱们可以把 key 理解成列表里每个元素的 “名字牌”,作用是让 Vue 能清清楚楚认出谁是谁,避免搞错。

先看个生活例子:

假设你在班里管理 3 个同学的作业本,分别是小明、小红、小刚的。

  • 没有 “名字牌”(key)的情况:你只按位置记:第 1 本是小明的,第 2 本是小红的,第 3 本是小刚的。突然,小红和小刚换了座位,你还是按位置看,就会把小刚的作业本当成小红的,完全搞错了。
  • 有 “名字牌”(key)的情况:每个作业本上都写了名字(小明、小红、小刚)。不管他们怎么换座位,你只要看名字就知道 “这本是小红的,那本是小刚的”,绝对不会乱。

Vue 里的 key 就是这个道理

Vue 渲染列表时,会生成虚拟的 DOM 节点。当列表数据变化(比如增删、排序),Vue 需要对比新旧列表,决定哪些节点要保留、哪些要修改。

  • 没有 key:Vue 就按 “位置” 对比,可能把 A 的节点错当成 B 的来复用,导致数据和节点对不上(比如输入框内容乱跳)。
  • 有 key:Vue 会按 key 这个 “名字牌” 精准匹配,相同 key 的节点直接复用,不同的才重新创建,既准确又高效。

具体案例:为什么不能用索引当 key

假设有个待办列表,用索引 index 当 key

vue

<!-- 初始列表 -->
<ul>
  <li v-for="(item, index) in list" :key="index">
    <input type="checkbox"> {{ item.name }}
  </li>
</ul>

// 数据
list = [
  { name: '吃饭' },
  { name: '睡觉' },
  { name: '打游戏' }
]

此时 key 是 0、1、2,对应 “吃饭”“睡觉”“打游戏”。如果你勾选了 “睡觉”(第 2 项,key=1),然后删除第 1 项 “吃饭”,列表变成:

// 新数据
list = [
  { name: '睡觉' },
  { name: '打游戏' }
]

这时新列表的 key 变成 0、1,Vue 会认为:

  • 原来 key=0 的 “吃饭” 被删了
  • 原来 key=1 的 “睡觉” 现在变成 key=0 了
  • 原来 key=2 的 “打游戏” 现在变成 key=1 了

结果就是:你勾选的 “睡觉” 会莫名其妙跑到 “打游戏” 前面,因为 Vue 按 key 复用了节点,位置乱了。

正确做法:用唯一不变的 id 当 key

vue

<ul>
  <li v-for="item in list" :key="item.id">  <!-- 用id当key -->
    <input type="checkbox"> {{ item.name }}
  </li>
</ul>

// 数据(每个item有唯一id)
list = [
  { id: 1, name: '吃饭' },
  { id: 2, name: '睡觉' },
  { id: 3, name: '打游戏' }
]

这时每个元素的 key 是 1、2、3(永远不变)。就算删除第 1 项,新列表的 key 是 2、3,Vue 能精准匹配到原来的 “睡觉” 和 “打游戏”,勾选状态也不会乱。

总结

key 就是列表元素的 “唯一名字牌”,让 Vue 不会因为位置变化认错元素。记住两点:

  1. 别用索引当 key(位置会变,名字牌就失效了);
  2. 最好用数据自带的唯一 id 当 key(像身份证号一样稳定)。