为什么 Vue 中不要用 index 作为 key


```javascript
Vue 中的 key 是用来做什么的?为什么不推荐使用 index 作为 key
  • 1
  • 2
{ tag: 'ul', children: [ { tag: 'li', children: [ { vnode: { text: '1' }}] }, { tag: 'li', children: [ { vnode: { text: '2' }}] }, ] } 假设更新以后,我们把子节点的顺序调换了一下 { tag: 'ul', children: [ + { tag: 'li', children: [ { vnode: { text: '2' }}] }, + { tag: 'li', children: [ { vnode: { text: '1' }}] }, ] } 这里的 children 部分是我们本文 diff 算法要讲的重点(敲黑板)。 响应式数据更新后,触发了 渲染 Watcher 的回调函数 vm._update(vm._render())去驱动视图更新 _render() 其实生成的就是 vnode,而 vm._update 就会带着新的 vnode 去走触发 __patch__ 过程 直接进入 ul 这个 vnode 的 patch 过程。 为什么不要以index作为key?
简单的列表组件,渲染出来 1 2 3 三个数字。我们先以 index 作为key,来跟踪一下它的更新。 item 列表节点的更新,在首次渲染的时候,我们的虚拟节点列表 oldChildren 粗略表示是这样的 [ { tag: "item", key: 0, props: { num: 1 } }, { tag: "item", key: 1, props: { num: 2 } }, { tag: "item", key: 2, props: { num: 3 } } ]; 在我们点击按钮的时候,会对数组做 reverse 的操作。那么我们此时生成的 newChildren 列表是这样的: [ { tag: "item", key: 0, props: { + num: 3 } }, { tag: "item", key: 1, props: { + num: 2 } }, { tag: "item", key: 2, props: { + num: 1 } } ]; **为什么不要用随机数作为key** **首先 oldVnode 是这样的** [ { tag: "item", key: 0.6330715699108844, props: { num: 1 } }, { tag: "item", key: 0.25104533240710514, props: { num: 2 } }, { tag: "item", key: 0.4114769152411637, props: { num: 3 } } ]; 更新·之后· [ { tag: "item", + key: 0.11046018699748683, props: { + num: 3 } }, { tag: "item", + key: 0.8549799545696619, props: { + num: 2 } }, { tag: "item", + key: 0.18674467938937478, props: { + num: 1 } } ]; diff 子节点的首尾对比如果都没有命中,就会进入 key 的详细对比过程,简单来说,就是利用旧节点的 key -> index 的关系建立一个 map 映射表,然后用新节点的 key 去匹配,如果没找到的话,就会调用 createElm 方法 重新建立 一个新节点 diff 子节点的首尾对比如果都没有命中,就会进入 key 的详细对比过程,简单来说,就是利用旧节点的 key -> index 的关系建立一个 map 映射表,然后用新节点的 key 去匹配,如果没找到的话,就会调用 createElm 方法 重新建立 一个新节点 用组件唯一的 id(一般由后端返回)作为它的 key,实在没有的情况下,可以在获取到列表的时候通过某种规则为它们创建一个 key,并保证这个 key 在组件整个生命周期中都保持稳定。 别用 index 作为 key,和没写基本上没区别,因为不管你数组的顺序怎么颠倒,index 都是 0, 1, 2 这样排列,导致 Vue 会复用错误的旧子节点,做很多额外的工作。 千万别用随机数作为 key,不然旧节点会被全部删掉,新节点重新创建,你的老板会被你气死。

你可能感兴趣的:(为什么 Vue 中不要用 index 作为 key)