面试官:为什么v-for一定要有唯一值做key?

351 阅读3分钟

前言

在Vue中,使用 v-for 指令渲染列表是一个常见的使用。当我们在渲染列表时,Vue 提供了 key 属性来帮助我们更有效地管理和维护列表的状态。本文将深入探讨为什么在Vue列表中要加上 key 属性的原因以及它的作用。

什么是 key 属性?

key 是 Vue 提供的一个特殊属性,用于标识 Vue 实例中的虚拟 DOM 元素,以便在更新过程中识别节点。在 v-for 中,key 被用于追踪每个节点的身份,确保在列表发生变化时,Vue 能够高效地更新 DOM,而不必重新创建整个列表。

<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

上述代码中,:key="item.id" 中的 item.id 就是 key 属性,它用于唯一标识列表中的每一项。

为什么需要添加 key 属性?

1.优化 DOM 操作

因为使⽤ key 相当于给 vnode 添加上⼀个唯⼀的 id,主要是在 DOM DIFF算法中使用的下⾯我们看个例⼦:

<div v-for="num in numbers" :key="num.id">
    {{num}}
</div>

items 的值为 [1,2,3,4,5,6,7,8,9,10] 那么就是渲染出⼗个div 是吧。如果没有 key ,那么当我们现在 items 的值变为 [0,1,2,3,4,5,6,7,8,9] 呢,那么第⼀个原来是 “1” 的 div内容变为“0”,⽽原来是“2”的div内容变为“1”...以此类推。(因为没有key属性,Vue无法跟踪每个节点,使⽤的是“就地复⽤” 得策略,通过这样的方法来完成变更)

但是如果key的情况下,Vue能跟踪每个节点,就会直接新增⼀个 div 添加到内容是“1”的div前⾯。根据key,更 准确, 更快的找到对应的vnode节点。设置key能够大大减少对⻚⾯的DOM操作,提⾼了diff效率,更加的高效更新虚拟DOM。

为什么key最好不要用索引index呢?

因为如果使用数组索引 index 为key, 当向数组中指定位置插⼊⼀个新元素后,因为这时候会重新更新 index索引,对应着后面的虚拟DOM的 key值全部更新了,这时候做的更新是没有必要的,就像没有加key⼀样, 因此index虽然能够解决key不冲突的问题,

2.处理可复用的元素

有时,我们希望列表中的某些元素能够被复用,而不是重新创建。例如,一个输入框的焦点状态,我们希望在列表项变动时,能够保持输入框的焦点状态。

vueCopy code
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <input v-model="item.value" />
    </li>
  </ul>
</template>

在上述情况下,如果没有 key 属性,输入框的焦点状态可能会在列表变动时丢失,因为 Vue 会尽量复用已存在的 DOM 元素,而不会考虑其内部状态。

总结

关于在 v-for 中使⽤ key 是因为使⽤ key 相当于给节点添加上⼀个唯⼀的 id,在 DOM DIFF算法中能更有效的更新虚拟DOM当没有使⽤的时候,如果我们需要对⼀个循环渲染的列表插⼊⼀个,那么实际上会 “就地复⽤” 的策略,⽐如我们需要在最前⾯插⼊⼀个,那么就会后⾯的全部往后变更,发生多次DOM操作,这是因为 Vue⽆法跟踪每个节点,⽽使⽤ key 后,节点标识,定位到最前面,然后插⼊修改,只发生一次DOM操作,大大优化了性能。