虚拟DOM和DOM Diff

120 阅读3分钟

一、虚拟DOM

1.概念

虚拟DOM本质是JS对象,通过JS的object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点

① 操作dom性能开销大,dom元素是非常庞大的,因为浏览器的标准把DOM设计的非常复杂。频繁地去做DOM更新,会产生一定的性能问题。 如下图所示 image.png ②真实DOM转换成虚拟DOM 虚拟DOM就是一个普通的JavaScript对象,包含了tagpropschildren三个属性

<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'
     ]
   }
 ]
}

引用segmentfault.com/a/119000002…

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值相同,互相对比,没有变化,不操作。