浏览器渲染页面

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

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

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

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

绘制过程以下:node

>浏览器

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

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

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

提到首绘这里来提两个概念: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变化都会影响几何属性,好比改变一个元素的背景色并不会影响元素的宽和高,这种状况下只会发生重绘。 
由于重排和重绘的耗时是巨大的因此应当尽量减小重排和重绘。

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