> 文章列表 > Vue中key的作用和原理

Vue中key的作用和原理

Vue中key的作用和原理

如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。key 是为 Vue 中 vnode 的唯一标记,通过key, diff 操作可以更准确、更快速

diff过程可以概括为:oldCh和newCh各有两个头尾的变量StartIdx和EndIdx,它们的2个变量相互比较,一共有4种比较方式。如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦StartIdx>EndIdx表明oldCh和newCh至少有一个已经遍历完了,就会结束比较,这四种比较方式就是首、尾、旧尾新头、旧头新尾

相关代码

// 判断两个vnode的标签和key是否相同 如果相同 就可以认为是同一节点就地复用
function isSameVnode(oldVnode, newVnode) {return oldVnode.tag === newVnode.tag && oldVnode.key === newVnode.key;
}// 根据key来创建老的儿子的index映射表  类似 {'a':0,'b':1} 代表key为'a'的节点在第一个位置 key为'b'的节点在第二个位置
function makeIndexByKey(children) {let map = {};children.forEach((item, index) => {map[item.key] = index;});return map;
}
// 生成的映射表
let map = makeIndexByKey(oldCh);
  • key是为Vue中的VNode标记的唯一id,在patch过程中通过key可以判断两个虚拟节点是否是相同节点,通过这个key,我们的diff操作可以更准确、更快速
  • diff算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的key与旧节点进行比对,然后检出差异
  • 尽量不要采用索引作为key
  • 如果不加key,那么vue会选择复用节点(Vue的就地更新策略),导致之前节点的状态被保留下来,会产生一系列的bug
  • 更准确 :因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
  • 更快速 :key的唯一性可以被Map数据结构充分利用,相比于遍历查找的时间复杂度O(n),Map的时间复杂度仅仅为O(1),比遍历方式更快。
  • key的作用主要是为了更高效的更新虚拟DOM
  • vue在patch过程中 判断两个节点是否是相同节点是key是一个必要条件 ,渲染一组列表时,key往往是唯一标识,所以如果不定义key的话,vue只能认为比较的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能
  • 实际使用中在渲染一组列表时key必须设置,而且必须是唯一标识,应该避免使用数组索引作为key,这可能导致一些隐蔽的bug;vue中在使用相同标签元素过渡切换时,也会使用key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果
  • 从源码中可以知道,vue判断两个节点是否相同时主要判断两者的key和标签类型(如div)等,因此如果不设置key,它的值就是undefined,可能永远认为这是两个相同节点,只能去做更新操作,就造成了大量的dom更新操作,明显是不可取的