原生DOM VS 虚拟DOM

1,105 阅读3分钟

1.概念:

<1>原生DOM:浏览器从服务器端读取html页面,浏览器将html解析成一棵元素嵌套关系的DOM树,用对象来表示页面上的元素,并提供操作DOM对象的api。

<2>虚拟DOM:保存了一棵DOM树被渲染之前所包含的所有信息,而这些信息可以通过对象的形式一直保存在内存中,并通过JavaScript的操作进行维护。


2.对比:

<1>我们先来看看浏览器渲染引擎工作流程:创建DOM树-->创建StyleRules-->创建Render树-->布局layout-->绘制painting,

第一步:用HTML分析器,分析HTML元素,构建一棵DOM树(标记化和树构建)

第二步:用css分析器,分析css文件和元素上的inline样式,生成页面的样式表

第三步:将DOM树和样式表,关联起来,构建一棵Render树(Attachment),每个DOM节点都有attach方法,接受样式信息,返回一个render对象。这些render对象最终会被构建一棵Render树

第四步:有了Render树,浏览器开始布局,为每个Render树上的节点确定一个在显示屏上出现的精确坐标

第五步:render树和节点显示坐标都有了,就调用每个节点paint方法,把它们绘制出来

如图:

                        webkit渲染引擎工作流程

注意: 

1>构建DOM树是一个渐进过程,为达到更好用户体验,渲染引擎会尽快将内容显示在屏幕上。

2>CSS解析是从右往左逆向解析的,嵌套标签越慢,解析越慢


<2>由上面分析可以看到传统的开发模式,原生js或者JQ操作DOM时候,浏览器会从构建DOM树开始从头到尾执行一遍流程。比如,在一次操作中,需要更新10个DOM节点,浏览器收到第一个请求后并不知道还有9次更新操作,因此会马上执行流程,最终执行10次。例如,第一次计算完,紧接着下一个DOM更新请求,这个节点的坐标值就变了,前一次计算为无用功。计算DOM节点坐标值等都是白白浪费的性能。即使计算机硬件一直在迭代更新,操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验。

<3>虚拟DOM就是为了解决浏览器性能问题而被设计出来的,如上例,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。

<4>原生dom操作vs通过框架封装的虚拟dom操作,这是一个性能vs可维护性的取舍,框架的意义在于为你掩盖底层的DOM操作,让给你用更声明式的方式来描述你的目的,从而让你的代码更容易维护。注意:没有任何框架可以比手动的优化DOM操作更快!因为dom操作层需要应对任何上层API可能产生的操作,它的实现必须是普适的。