了解虚拟DOM和diff算法

216 阅读3分钟

今天分享一下虚拟DOM和diff算法,当然,只是非常简单的了解一下,知道这两个东西的概念。

起初我还一直把DOM当做是标签的那些元素,后来才知道,我们说的DOM全称 Document Object Model,即文档对象模型,是JavaScript的对象,用来表示页面标签的元素,这个对象提供了一系列操作DOM的API。也就是说DOM是js用来表示元素的对象,我们可以通过这个对象去操作页面的元素。可以理解成DOM是标签元素的映射,是一一对应的,但是DOM是JavaScript的一个对象。

虚拟DOM,是框架中的概念,是开发框架的人用js对象来模拟DOM元素和嵌套关系,本质就是用JS对象来模拟DOM。目的就是为了实现页面元素的高效更新。这边有个网址可以去看看标签生成的虚拟DOM的对象:

hcysun.me/vue-templat…

比如我们写两个标签:

生成的模拟DOM的对象:

{

"type": 1,

"tag": "div",

"attrsList": [],

"attrsMap": {},

"rawAttrsMap": {},

"children": [

    {

        "type": 1,

        "tag": "p",

        "attrsList": [],

        "attrsMap": {},

        "rawAttrsMap": {},

        "parent": "[循环引用]",

        "children": [],

        "plain": true,

        "static": true

    }

],

"plain": true,

"static": true,

"staticInFor": false,

"staticRoot": true,

"staticProcessed": true

}

那我们为什么要使用虚拟DOM呢?比如我们要同时请求三个接口,不同接口需要在页面操作不同的标签,这时候每一个接口都去操作一次DOM,这样一遍一遍的渲染DOM在浏览器里面是非常耗费性能的。虚拟DOM不一样,虚拟DOM会把旧的结构和最新的结构对比,然后比较出差异,最后以最小的修改去更新真实的DOM。之前也分享过,Vue在一个同步任务过程中是不会去更新渲染视图,而是在同步任务(事件循环队列)执行完毕之后,在主线程的同步执行完毕,读取任务队列时更新视图。

而怎么快速比较新旧虚拟DOM是有一个叫diff的算法,各个框架的diff算法应该大体上区别不大,diff,different的意思。我去查了一些资料,diff算法大概分成三大块:

Tree diff:

新旧两个DOM树一层一层对比,从头到尾逐层对比完了之后,所有需要更新的元素都找了出来了。

Component diff:

在tree diff之后,有更新的一层里面开始进行组件级别的对比,如果组件相同,暂时组件不对比,如果不同,则移除旧组件,创建新组件。

Element diff:组件对比的时候,如果组件类型相同,就开始进行元素级别的对比,这一步之后其实就把所有差异都找出来了。

具体的源码什么的暂时无能为力,大概的原理就是这样。

其实今天的分享挺鸡肋的,只是了解一下什么是虚拟DOM和diff算法的表面东西。不过自己以前连这么鸡肋的东西都不知道,所以记录一下。