Vue中的虚拟DOM
背景
众所周知,在网页中最大的开销就是DOM操作,DOM很慢而且非常庞大。原生 js 或 jq 操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。在一次操作中,我需要更新10个节点,浏览器不知道共有10个节点要更新,就会执行10次更新操作,浪费性能,使页面出现卡顿,影响用户体验。
于是,就出现了虚拟DOM
虚拟DOM的流程
- 在内存中生成一颗虚拟dom树
- 将内存中的虚拟dom树初始化渲染成真实dom树
- 当我们修改数据的时候,将之前的虚拟dom树结合数据生成新的虚拟dom树
- 将生成的虚拟dom与上一次的虚拟dom树结构进行对比,对比差异(diff算法)
- 将对比出来的差异部分重新真实dom结构渲染
优点:
当数据变化的时候,大量操作的是虚拟dom,属于内存数据,操作起来性能要高很多,而真实的dom操作,只有在追加的那一刻才会进行操作,大大提升了性能
虚拟dom的diff算法
两颗完全的树差异比较一个时间复杂度为 O(n^3)。但是在我们的web中很少用到跨层级DOM树的比较,所以平层(一个层级跟一个层级对比),这样算法复杂度就可以达到 O(n)。如下图
平层Diff,只有以下4种情况:
- 如果是节点类型改变,直接将旧节点卸载替换为新节点,旧节点包括下面的子节点全部卸载
- 节点类型不变,属性或属性值改变,不会卸载节点,执行节点更新的操作
- 文本改变,直接修改文字内容
- 移动、增加、删除子节点时
如果想在中间插入节点F,简单粗暴的做法是:卸载C,装载F,卸载D,装载C,卸载E,装载D,装载E。如下图:
如果没有给数组或枚举类型定义一个key,就会采用以上粗暴的算法
如果为元素增加key后,Vue就能根据key,直接找到具体的位置进行操作,效率比较高。如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3Bu0yHZ-1584981903776)(image-20200324004229970.png)]
在v-for中提供key,一方面提高性能,一方面避免出错