1.什么是虚拟DOM
本质上来说,虚拟DOM是一个简单的JS对象,并且最少包含tag,props和children三个属性。
不同的框架对这三个属性的命名会有差别。他们分别是标签名(tag), 属性(props) ,和子元素对象 (children).下面是一个典型的虚拟DOM对象例子:
虚拟DOM1.png虚拟DOM和dom对象有一一对应的关系,上面的虚拟DOM是由下面的HTML生成的:
[图片上传失败...(image-afc6e3-1621752815399)]
一个DOM对象,比如 li , 由 tag(li) , props ({ id:1 ,class: 'li-1'}) 和 children ( ['第' ,1 ])三个属性来描述。
2.为什么需要虚拟DOM
总结:
1. 有效解决浏览器的性能问题,提高页面的解析速度
2. 配合不同的渲染工具,使之可以跨平台渲染
虚拟DOM最大的特点就是将页面的状态抽象为jS对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。此外,进行页面更新时,借助虚拟DOM,DOM元素的改变可以在内存中进行比较,在结合框架的事务机制,将 多次比较的结果合并后 一次性的更新到页面,从而有效的减少页面渲染的次数。
Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化,
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
3.虚拟DOM的更新步骤
使用虚拟DOM的框架,一般的设计思路都是 页面等于页面状态的映射,即 UI=render(state)。当页面需要更新时,无序关心DOM具体的变化方式,只要改变state即可。剩下的事(render)就叫给框架来做。在DOM状态发生改变时,虚拟DOM会进行diff运算,来更新只需要被替换的DOM,而不是全部,我们举个最简单的情况,当state发生变化时,我们重新生成整个虚拟DOM,触发比较的操作,上述过程分为以下四步:
state变化,生成新的虚拟DOM--比较新旧DOM的异同-生成差异对象--遍历差异对象并更新DOM
-
state 变化,生成新的虚拟DOM
-
比较新的虚拟DOM和之前的虚拟DOM的异同
-
生成差异对象(patch)
-
遍历差异对象并更新DOM
4.key的加入
通过加入唯一表示符key,很好的提高了更新元素(diff算法)的效率。(只更新key不同的DOM,其余的保持不变)
5.对虚拟DOM的深入理解
-
真实DOM及其解析流程
页面渲染流程大致要经历5个流程:
1. 创建DOM树--创建styleRules对象--
2. 整合DOM和styleRules,创建render树--【render树只包含了用于渲染页面的节点】
3. 根据确定的位置,开始布局(layout)--
4 . 绘制页面(painting)
-
用HTML分析器,分析HTML元素,构建一颗DOM树(标记化和树构建)。
-
用CSS分析器,分析CSS文件和元素上的inline样式,生成页面的样式表。
-
将DOM树和样式表,关联起来,构建一颗Render树(这一过程又称为Attachment)。每个DOM节点都有attach方法,接受样式信息,返回一个render对象(又名renderer)。这些render对象最终会被构建成一颗Render树。
-
有了Render树,浏览器开始布局,为每个Render树上的节点确定一个在显示屏上出现的精确坐标。
-
Render树和节点显示坐标都有了,就调用每个节点paint方法,把它们绘制出来。
-
对于浏览器解析DOM的一些问题
-
DOM树的构建是文档加载完成开始的?
构建DOM数是一个渐进过程,为达到更好用户体验,渲染引擎会尽快将内容显示在屏幕上。它不必等到整个HTML文档解析完毕之后才开始构建render数和布局。
-
Render树是DOM树和CSSOM树构建完毕才开始构建的吗?
这三个过程在实际进行的时候又不是完全独立,而是会有交叉。会造成一边加载,一遍解析,一遍渲染的工作现象。
-
CSS的解析是从右往左逆向解析的(从DOM树的下-上解析比上-下解析效率高),嵌套标签越多,解析越慢。(也就是从内部css开始解析)
浏览器解析过程图.png
-
网友评论