本文是作者个人对Vue的key原理总结,文中引用的图片出自王红元老师vue3课程,想要更加深入的理解key的实现过程及源码解析,可以去搜索coderwhy王红元老师vue3课程中观看对vue中key的原理讲解及源码解析
v-for中的key是什么作用?
在使用v-for进行列表渲染时,我们通常会给元素或者组件绑定一个key属性。
官方中对key的作用解释:
- key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes;
- 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
- 而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
vue处理key的核心是用到diff虚拟dom算法
认识VNodes
- VNode的全称是Virtual Node,也就是虚拟节点;
- 事实上,无论是组件还是元素,它们最终在Vue中表示出来的都是一个个VNode;
- VNode的本质是一个JavaScript的对象;
认识虚拟DOM
- 如果我们不只是一个简单的div,而是有一大堆的元素,那么它们应该会形成一个VNode Tree:
Vue源码中在对于有key和没key是不同的处理情况
没有key的过程
没有key,会使用 patchUnkeyedChildren方法;
有key的过程
有key,那么就使用 patchKeyedChildren方法;
diff算法的过程
没有key时,对于VNodes列表的新旧对比过程:
- c和d来说它们事实上并不需要有任何的改动;
- c被f所使用了,所有后续所有的内容都要一次进行改动,并且最后进行新增;
有key时,对于VNodes列表的新旧对比过程:
①第一步的操作是从头开始进行遍历、比较:
- a和b是一致的会继续进行比较;
- c和f因为key不一致,所以就会break跳出循环;
②第二步的操作是从尾部开始进行遍历、比较:
③第三步是如果旧节点遍历完毕,但是依然有新的节点,那么就新增节点:
④第四步是如果新的节点遍历完毕,但是依然有旧的节点,那么就移除旧节点:
⑤第五步是最特色的情况,中间还有很多未知的或者乱序的节点:
总结
Vue在进行diff算法的时候,会尽量利用我们的key来进行优化操作:
- 在没有key的时候我们的效率是非常低效的;
- 在进行插入或者重置顺序的时候,保持相同的key可以让diff算法更加的高效;