在 `Vue` 中为什么不推荐用 `index` 做 `key`

344 阅读3分钟

Vue 中为什么不推荐用 indexkey

具体diff解释可以看看第十题

Vue3.0中 在 patchChildren 方法中有这么一段源码

patchChildren 根据是否存在 key 进行真正的 diff 或者直接 patch(也就是直接用新的节点替换掉旧的节点)

  • 同步头部节点

    第一步的事情就是从头开始寻找相同的 vnode,然后进行 patch ,如果发现不是相同的节点,那么立即跳出循环。

    isSameVNodeType 作用就是判断当前 vnode 类型 和 vnodekey 是否相等

    key 在 diff 算法的作用,就是用来判断是否是同一个节点

  • 同步尾部节点

    第二步从尾开始同前 diff

    经历第一步操作之后,如果发现没有 patch 完,那么立即进行第二步,从尾部开始遍历依次向前 diff。如果发现不是相同的节点,那么立即跳出循环。

  • 添加新的节点

    第三步如果老节点全部 patch,新节点没有被 patch 完,创建新的 vnode

  • 删除多余节点

    第四步如果新节点全部被 patch,老节点有剩余,那么卸载所有老节点

⭐为什么不要用index

  • 性能消耗

    使用 index 做 key,破坏顺序操作的时候, 因为每一个节点都找不到对应的 key导致部分节点不能复用,所有的新 vnode 都需要重新创建。

    当我们在前面加了一条数据时 index 顺序就会被打断,导致新节点 key 全部都改变了,所以导致我们页面上的 数据都被重新渲染了。

用唯一值作为 key 可以节约开销

  • 数据错位

    往 input 里面输入一些值,添加一位同学效果: 采用 index 作为 key 时,当在比较时,发现虽然文本值变了,但是当继续向下比较时发现 DOM 节点还是和原来一摸一样,就复用了,但是没想到 input 输入框残留输入的值,这时候就会出现输入的值出现错位的情况

  • 解决方案

    既然知道用 index 在某些情况下带来很不好的影响,那平时我们在开发当中怎么去解决这种情况呢?其实只要保证 key 唯一不变就行,一般在开发中用的比较多就是下面三种情况。

  1. 在开发中最好每条数据使用唯一标识固定的数据作为 key,比如后台返回的 ID,手机号,身份证号等唯一值
  2. 可以采用 Symbol 作为 key,Symbol 是 ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名
let a = Symbol('测试')
let b = Symbol('测试')
console.log(a===b)//false
  1. 可以采用 uuid 作为 keyuuid 是 Universally Unique Identifier 的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符

⭐总结

关键词:破坏顺序-----输入类的DOM-----唯一标识的key

  • 用 index 作为 key 时,在对数据进行,逆序添加,逆序删除等破坏顺序的操作时,会产生没必要的真实 DOM更新,从而导致效率低
  • 用 index 作为 key 时,如果结构中包含输入类的 DOM,会产生错误的 DOM 更新
  • 在开发中最好每条数据使用唯一标识固定的数据作为 key,比如后台返回的 ID,手机号,身份证号等唯一值
  • 如果不存在对数据逆序添加,逆序删除等破坏顺序的操作时,仅用于渲染展示用时,使用 index 作为 key 也是可以的(但是还是不建议使用,养成良好开发习惯)。
  • key作为虚拟DOM对象的唯一标识diff算法中起到了至关重要的作用

\