v-for 循环为什么要绑定 key,作用是什么?

1 阅读2分钟

一般解释: 在 Vue.js 中,使用 v-for 指令进行循环渲染时,通常建议绑定一个唯一的 key 属性到循环的元素上。 key 的作用是帮助 Vue 识别每个循环项,以便在数据变化时更高效地更新虚拟 DOM 和 实际 DOM。 下面是 key 的作用和原因:

  1. 识别元素:key 用于标识每个循环生成的元素。当数据发生变化时,Vue 使用 key 来判断哪些元素是新添加的、哪些是删除的,以便进行高效的更新。
  2. 优化性能:如果没有指定 key,Vue 可能会难以识别元素的唯一性,从而导致一些性能问题。有时,删除或更新元素可能会变得低效,因为 Vue 需要进行全面的比较。
  3. 保持状态:如果没有 key,在某些情况下可能会导致不正确的状态保持。特别是在表单元素等需要保持用户输入状态的情况下,key 可以确保正确的状态被维护。
  4. 处理动态数据:当数据中的元素顺序变化时,key 可以帮助 Vue 正确地识别元素的位置和变化,从而避免渲染错误。 一般来说,key 应该是具有唯一性的标识符,可以是元素的 ID 、索引或其他唯一值。不推荐使用随机树或时间戳作为 key,因为这可能会导致不稳定的行为,尤其在数据变化频繁的情况下。

从源码的角度来解释: v-for 通常应用在 一组 DOM 的循环中。当这组 DOM 的数据发生变化时,就会两组DOM 的更新,例如:

原数组:[a, b, c]
新数组:[a, b, d]

这两组 DOM 的更新就会触发 diff 算法。“添加 key 优化性能”其实指的就是优化diff算法。 在 diff 中:如果 新 DOM 和旧 DOM 是同一个 DOM 节点,则旧 DOM 不需要销毁重新创建。Vue 就是通过 key 和 节点名 共同判断 DOM 是否是同一个节点的。

源码:

export function isSameVNodeType(n1: VNode, n2: VNode): boolean {
  return n1.type === n2.type && n1.key === n2.key
}

type 标识的是节点类型,例如 li、ul、div、img
key 是 v-for 循环中的 key 属性

所以如果 key 属性不设置,则会导致 Vue 无法判断两个 DOM 节点是否为同一个 DOM 节点。从而导致 diff 无法进行,影响性能。