Vue 中的 Key 的原理

1. 什么是 key

开始之前,我们先还原两个实际工作场景。

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

用 +new Date() 生成的时间戳作为 key,手动强制触发重新渲染:

<组件 :key="+new Date()" />

key 是给每一个 vnode 的唯一 id,也是 diff 的一种优化策略,可以根据 key 更准确、更快地找到对应的 vnode 节点。

当我们在使用 v-for 时,需要给单元加上 key。用 +new Date() 生成的时间戳作为 key,手动强制触发重新渲染。

2. 设置 key 与不设置 key 的区别

举个例子:创建一个实例,2 秒后往 items 数组插入数据。

<body>
  <div id="demo">
    <p v-for="item in items" :key="item">{{ item }}</p>
  </div>
  <script src="../../dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#demo',
      data: { items: ['a', 'b', 'c', 'd', 'e'] },
      mounted() {
        setTimeout(() => {
          this.items.splice(2, 0, 'f')
        }, 2000)
      }
    })
  </script>
</body>

不使用 key 的情况

vue 会进行这样的操作:分析下整体流程,一共发生了 3 次更新,1 次插入操作。

使用 key 的情况

vue 会进行这样的操作:一共发生了 0 次更新,1 次插入操作。

通过上面两个小例子,可见设置 key 能够大大减少对页面的 DOM 操作,提高了 diff 效率。

设置 key 值一定能提高 diff 效率吗?

其实不然,文档中也明确表示:

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态(例如:表单输入值)的列表渲染输出。

建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

来源整理自:vue3js.cn 面试官系列