引用文章
浏览器能够对以下文件进行解析,HTML,SVG和XHTML;解析生成DOM树;javascript脚本文件会通过DOM API 和CSSOM API操控DOM Tree;CSS文件解析生成CSS Rule Tree。
解析完成后浏览器引擎会根据生成的DOM树和CSS规则树构建渲染树;但渲染树不一定等同于DOM树因为元素中display:none或者其他的一些标签不会放在渲染树中进行渲染。
CSS规则树会匹配到渲染树中的每个元素(DOM节点),并给它们加上CSS Rule。然后计算每个元素的位置,这个过程叫做回流(reflow)。最后通过调用操作系统Native GUI的API绘制。
DOM树的解析过程(Firefox)
<html>
<html>
<head>
<title>Web page parsing</title>
</head>
<body>
<div>
<h1>Web page parsing</h1>
<p>This is an example Web page.</p>
</div>
</body>
</html>
上述代码的DOM树会被解析成这样:
CSS规则树的解析过程(Firefox)
<doc>
<title>A few quotes</title>
<para>
Franklin said that <quote>"A penny saved is a penny earned."</quote>
</para>
<para>
FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>
</para>
</doc>
CSS代码如下:
/* rule 1 */ doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }
CSS规则树图中rule4出现了2次,一次是独立的,另一次在规则3的子节点,建立CSS规则树是按照DOM树的结构来建立的。PS(CSS匹配DOM树是一个非常耗性能和复杂的事情所以DOM树要小,CSS尽量用id和class,不要过度层叠下去)
根据DOM树和CSS规则树匹配构造一个Style Context Tree;然后关联Style Context Tree和渲染树。
接下来就是渲染:
渲染的流程基本上如下(黄色的四个步骤):
计算CSS样式
构建Render Tree
Layout – 定位坐标和大小,是否换行,各种position, overflow, z-index属性 ……
正式开画
reflow和repaint
*(为什么不能用CSS通配符 ,CSS选择器层叠为什么不能超过三层,CSS为什么尽量使用类选择器,书写HTML为什么少使用table,为什么结构要尽量简单-DOM树要小….)
Reflow:对于DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式(浏览器的、开发人员定义的等)来计算并根据计算结果将元素放到它该出现的位置,这个过程称之为reflow。
Repaint:当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器于是便把这些元素都按照各自的特性绘制了一遍,于是页面的内容出现了,这个过程称之为 repaint。
注意:回流必将引起重绘,而重绘不一定会引起回流
Reflow的成本要比Repaint大得多;DOM树每个节点都有一个Reflow方法,一个节点的Reflow方法有可能触及父节点或者其他节点的Reflow。
增删改DOM节点,移动DOM,做动画,修改CSS样式滚动页面,修改默认字体等等都会触发Reflow或Repaint。减少Reflow和Repaint的一些方法:
- 尽量预先定义好CSS的类,然后去修改DOM的className;
- 不要把DOM结点的属性值放在一个循环里当成循环里的变量;
- 为动画的HTML元件使用fixed或absoult的position,那么修改它们的CSS是不会reflow的;
- 尽可能的修改层级比较低的DOM。