一、虚拟DOM
1.概念
虚拟DOM本质是JS对象,通过JS的object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点
① 操作dom性能开销大,dom元素是非常庞大的,因为浏览器的标准把DOM设计的非常复杂。频繁地去做DOM更新,会产生一定的性能问题。
如下图所示
②真实DOM转换成虚拟DOM
虚拟DOM就是一个普通的JavaScript对象,包含了
tag、props、children三个属性
<div id="app">
<p class="text">TXM to SFM</p>
</div>
转换成虚拟DOM
{
tag: 'div',
props: {
id: 'app'
},
chidren: [
{
tag: 'p',
props: {
className: 'text'
},
chidren: [
'TXM to SFM'
]
}
]
}
2.优点
① 虚拟DOM可以减少DOM操作:
可将多次重复的操作合并为一次操作,减少操作次数。例如添加1000个节 点,原生DOM是 一个一个操作的,而虚拟DOM则可一次完成;
虚拟DOM可借助DOM diff 把多余的操作省掉,减少操作范围。例如添加1000个节点,其中仅10个节点是新的,DOM diff可通过前后对比识别出需要更新的这10个节点的并仅对其进行操作,这样就免去对其余990个节点的操作。
②可跨平台渲染: 不仅可以变成DOM,还可以变成小程序、IOS和安卓应用。
3.缺点
需要额外的创建函数,如Vue中的'createElement'函数和React中的'h'函数,其可以通过JSX语法或vue-loader等来转译,但是这样就比较依赖打包工具
二、DOM diff
1.概念
DOM diff是虚拟DOM的对比算法,简单来说,就是对比前后两棵DOM树的区别,如果有差异就记录到一个对象中,最后只对这些差异进行操作,以尽量少的操作完成DOM的增删和更新,避免多余的操作。
2.优点
使用DOM diff是,在实际代码中,其会对新旧两棵DOM树进行一个从类型到属性、从上到下、从父到子的深度遍历和对比,并将差异存到对象中,只对差异进行操作,而非像原生DOM一样完全的重新加载。
DOM diff算法使得DOM操作内容大幅减少,从而加快浏览器处理速度,提高性能。
3.问题与解决
DOM diff在同级节点对比时会出现问题,例如:
在A、B两个节点之间插入一个C节点,变成A、B、C的排列,最简单的操作是什么呢?当然是原有的A、B都不变,直接A与B之间添加C即可,但是实际流程并非如此。
实际情况是:将之后的"A、C、B"与之前的"A、B"这两组按下标进行逐个对比:A与A对比,不变,A保留下来;之前的B与之后的C对比,不相同,则会删掉B,加上C;最后,之后的B与之前的”空“对比,B作为新增内容加上。如此便进行了冗余的操作。
解决:给各个节点设置key值即可,key值相同才会进行对比。如:给上述A、C、B分别赋予key值“1,2,3”,则A与A对比,无变化,不操作;C因为key为2,和“空”比,直接加上;而B和B的key值相同,互相对比,没有变化,不操作。