阅读 966
浏览器DOM渲染解析过程总结

浏览器DOM渲染解析过程总结

浏览器DOM渲染解析过程总结

一、浏览器的主要组件(如下图所示)

在这里插入图片描述

备注:Interface表示人机交互界面。

  1. 用户界面(User Interface):是指浏览器功能模块的UI布局。例如:地址栏、前进/后台按钮、收藏夹等。不同浏览器他们的功能模块的UI布局是不一样的。
  2. 浏览器引擎(Browser engine):在UI界面和渲染引擎之间传递指令;同时操作数据存储(Data Persistence)对数据持久化处理;
  3. 渲染引擎(Rendering engine):主要负责将请求的布局文件、样式文件进行解析渲染呈现出Web页面;
  4. 网络(Networking):进行HTTP请求调用;
  5. JS解释器(JavaScript Interpreter):主要负责解析并执行JavaScript语言;
  6. 用户界面后端(UI Backend):用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
  7. 数据存储(Data Persistence):负责将数据在浏览器中进行持久化存储。例如:cookie、session、localStorage、indexDB等存储功能。

重点理解:Rendering engine(渲染引擎)、NetWorking(网络)、JavaScript Interpreter(JS引擎)、Data Persistence(数据存储)

二、浏览器生成DOM解析页面过程(如下图所示)

在这里插入图片描述
第一步:将载入的HTML文件解析成DOM树(DOM Tree),并且将各个标记标识解析成DOM树的各个节点;在解析HTML的同时会将CSS样式解析成CSS规则(CSS Rules)。

第二步:将解析成的DOM树和CSS规则进行关联生成渲染树(Render Tree)。

第三步:进入布局阶段,为DOM树的每个节点分配在屏幕上出现的确切坐标(这一阶段还是渲染树)

第四步:进入绘制阶段,在这里渲染引擎的工作就结束了,接下来就给用户界面后端(UI Backend)对渲染树的每个节点进行绘制,呈现出页面效果。

说明:为了提高页面呈现速度,渲染引擎采用的是渐进式渲染,也就是在边解析、边渲染的模式下进行工作的,它不必等着整个HTML解析完成再渲染。

疑问总结?

问: 为什么有些网页打开时过了几秒才有样式出现?
答:这个问题跟渲染引擎无关,主要由于请求CSS样式文件时网络延时造成。
复制代码

三、不同内核浏览器的DOM解析的差异性(如下图所示)

在这里插入图片描述

  • Webkit内核的浏览器:chrome、Safari
  • Gecko内核的浏览器:Firefox

从上图可知,Webkit和Gecko内核的渲染流程和机制整体上是一致的,它们的差异性总结:

  1. 术语上不一致,Webkit内核中DOM Tree(DOM树)、Render Tree(渲染树)、Layout(布局),Gecko内核中Content Model(内容模型)、Frame Tree(框架树)、Reflow(回流)。
  2. 在将HTML解析后Gecko比Webkit多一层,称为Content Sink(内容槽)。

四、JS操作DOM的性能优化方案

众所周知,直接用JS操作DOM是很浪费性能的。因为每次通过JS操作(访问/新增/删除/更新)DOM都会导致DOM Tree(DOM树)重新布局/回流、绘制(简称重排、重绘过程)。

重排: 当DOM节点信息发生变化,例如位置改变,DOM节点大小改变,都会对该DOM重新计算,并进行布局/回流操作(不同浏览器术语不一样);

****怎样会导致重排?****
1. 缩放浏览器窗口;
2. 改变页面中DOM节点大小或位置;
3. 通过innerHTML/innerText修改DOM节点上的字体信息。注意:文本也属于DOM节点之一(文本节点);
4. 通过JS的dom中style属性来改变DOM节点的样式;
5. 通过JS对DOM节点进行操作(访问/新增/删除/更新);
6. HTML页面首次呈现;
复制代码

重绘: 当DOM节点信息不发生变化时,只改变了DOM节点的外貌样式时(不改变DOM节点的位置和大小,只改变字体颜色或背景色等)。会对该DOM进行重新绘制。注意有重排必定会有重绘,有重绘不一定有重排;

  1. 通过变量缓存DOM对象引用,以此减少对DOM的直接操作;
//基本方式
for(var i=0;i<100;i++){
    var dom=document.getElementById("xxx");
    dom.innerHTML=dom.innerHTML+i;
}
//变量缓存DOM引用
var dom=document.getElementById("xxx");
for(var i=0;i<100;i++){
    dom.innerHTML=dom.innerHTML+i;
}
复制代码
  1. 使用createDocumentFragment()方法创建DOM碎片容器;
//基本方式
var dom=document.getElementById("xxx");
for(var i=0;i<100;i++){
    var cre_dom=document.createElement("xxx");
    dom.appendChild(cre_dom);
}
//使用createDocumentFragment
var dom=document.getElementById("xxx");
var cre_frag=document.createDocumentFragment();
for(var i=0;i<100;i++){
    var cre_dom=document.createElement("xxx");
    cre_frag.appendChild(cre_dom);
}
dom.appendChild(cre_frag);
复制代码
  1. 采用性能更优的querySelectAll()访问DOM节点;
  2. 使用CSS3动画机制,开启硬件加速,将渲染计算交给GPU;

参考文章:www.html5rocks.com/en/tutorial…

文章分类
前端
文章标签