在写vue代码的时候,经常有用到v-for这个指令来遍历数组或者对象,官方文档推荐我们在使用v-for的时候,加上key属性,并且说明这个key属性必须是唯一标识。key可加可不加,vue都做了处理,但是给到key属性的,在性能上会好一些,为什么呢,其实是和vue的虚拟DOM的Diff算法有关系。
key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes ;
如果不使用key, Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
首先,看看vue是怎么处理有key和没有key的:
没有key属性的时候,是怎么去更新DOM:执行patchUnkeyedChildren这个方法:
这个方法就是比较新旧虚拟节点的长度,以少的长度为准做patch比较,如果如果旧的节点比新的多,就删掉多余的节点,如果旧的比新的少,就创建新的节点。并且,如果节点类型相同但内容不同,就会保留节点但是更新内容(patch函数做的操作)。
patch函数是做了什么
源码中的位置如下,大致就是不同情况下,对vnode的处理(新增,更新,卸载)
有key属性的时候,是怎么去更新DOM:执行patchKeyedChildren这个方法:
先从头部开始遍历,判断新旧vnode是不是同一个节点(节点的type和key都相同),相同便patch,不相同就跳出循环来到第二步。
判断虚拟节点是否相同的方法是isSameVNodeType,key就是其中一个重要的判断节点相同的依据。
第二步就是从尾部开始遍历,相同的就进行patch,不同就跳出循环
第三步是进行挂载
第四步是进行卸载
第五步是特殊的,如果中间是不明序列,节点打乱了,有多了也有少了,那么会基于key的变化重新排列元素顺序,尽量复用相同的节点的前提下,移除/销毁key不存在的元素,挂载新增的节点。
看完vue对于有key无key时更新dom的不同处理,很明显,有key的时候,效率更高,所以官方才更推荐我们在使用v-for时绑定key。