浏览器渲染页面

HTML解析器输出的树是由DOM元素和属性节点组成的,它是HTML文档的对象化描述,也是HTML元素与外界(如Javascript)的接口。DOM与标签有着几乎一一对应的关系。 

  DOM树的构建过程为:将字节转换成字符,确定tokens,将tokens转换成节点,然后构建 DOM 树。

浏览器构建这个简单页面的 DOM 过程中,在文档的 head 中遇到了一个 link 标记,该标记引用一个外部 CSS 样式表:style.css。由于预见到需要利用该资源来渲染页面,它会立即发出对该资源的请求。并进行CSSDOM树的构建。

CSSOM 树和 DOM 树合并成渲染树,然后用于计算每个可见元素的布局,并输出给绘制流程,将像素渲染到屏幕上。

绘制过程如下:

>

  • DOM 树与 CSSOM树合并后形成渲染树,它只包含渲染网页所需的节点。遍历每个DOM树中的node节点,在CSSOM规则树中寻找当前节点的样式,生成渲染树。
  • 布局计算每个对象的精确位置和大小。
  • 最后一步是绘制,使用最终渲染树将像素渲染到屏幕上。

那么当资源中还有js时会发生什么?答案是阻塞DOM树的构建! 

脚本在文档的何处插入,就在何处执行。当 HTML 解析器遇到一个 script 标记时,它会暂停构建 DOM,将控制权移交给 JavaScript 引擎;等 JavaScript 引擎运行完毕,浏览器会从中断的地方恢复 DOM 构建。而因此就会推迟页面首绘的时间。

提到首绘这里来提两个概念:DOMContentLoaded和load

1.当 onload 事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了。 
2.当 DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash。

页面的首次绘制是在渲染树解析构建完毕之后。因此所需的关键资源是构建DOM树和CSSDOM的html和css。但是当执行js时会阻塞html的解析也就推迟了页面的首绘时间。该如何解决这个问题呢? 
可以在首绘不需要js的情况下用async和defer实现异步加载。这样就js就不会阻塞html的解析了。注意,异步执行是指下载。执行js时仍然会阻塞。


<script async src="siteScript.js" onload="myInit()"></script>  

<script defer src="siteScript.js" onload="myInit()"></script> 

以上两种方式都可以实现js的异步加载。那么两者之间有什么区别呢?

  • async 脚本在script文件下载完成后会立即执行,并且其执行时间一定在 window的load事件触发之前。这意味着多个async脚本很可能不会按其在页面中的出现次序顺序执行。
  • 与此相对,浏览器确保多个 defer 脚本按其在HTML页面中的出现顺序依次执行,且执行时机为DOM解析完成后,document的DOMContentLoaded 事件触发之前。

  由于async脚本执行顺序的不确定性因此不能用来加载具有明显依赖关系的js会造成乱序。

DOM树表示页面结构,渲染树表示DOM节点如何显示。DOM树中的每一个需要显示的节点在渲染树种至少存在一个对应的节点(隐藏的DOM元素disply值为none 在渲染树中没有对应的节点)。

渲染树中的节点被称为“帧”或“盒”,符合CSS模型的定义,理解页面元素为一个具有填充,边距,边框和位置的盒子。一旦DOM和渲染树构建完成,浏览器就开始显示(绘制)页面元素。

那么什么是重排和重绘呢 
当DOM的变化影响了元素的几何属性(宽或高),浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会因此受到影响。

浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为重排。完成重排后,浏览器会重新绘制受影响的部分到屏幕,该过程称为重绘。

由于浏览器的流布局,对渲染树的计算通常只需要遍历一次就可以完成。但table及其内部元素除外,它可能需要多次计算才能确定好其在渲染树中节点的属性,

通常要花3倍于同等元素的时间。这也是为什么我们要避免使用table做布局的一个原因。

并不是所有的DOM变化都会影响几何属性,比如改变一个元素的背景色并不会影响元素的宽和高,这种情况下只会发生重绘。 
因为重排和重绘的耗时是巨大的所以应当尽可能减少重排和重绘。

1、尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新) 
2、同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0) 
3、如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(fragment元素的应用) 
4、 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。

posted @ 2017-09-21 14:30  pursues  阅读(139)  评论(0编辑  收藏  举报