0%

2019-02-20 解析页面流程(2)生成CSS规则和构建渲染

生成 CSS 规则

同理,CSS 规则树的生成也是类似

1
Bytes -> character -> tokens -> nodes -> CSSOM
1
2
3
4
1.Conversion:浏览器将获得的HTML内容(Bytes)基于他的编码转换为单个字符
2.Tokenizing分词:浏览器按照HTML规范标准将这些字符转换为不同的标记token。每个token都他有自己独特的含义以及规则及
3.Lexing词法分析:分词的结果是得到了堆的token,此时把他们的转换为对象,这些对象分别定义了他们的属性和规则
4.DOM构建:因为HTML标记定义的就是不同标签之间的关系,这个关系就像是一个树形结构。

举个例子

CSS 代码

1
2
3
4
5
body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }

DOM 树:

image

构建渲染书

现在「CSS 树」和「DOM 树」都已经完成,浏览器现在要开始构建渲染树了。
一般情况,「渲染树」和「DOM 树」相对应的, 但是也不定,因为有些不可见的(display:none;)等等不可见的标签会影响「渲染树」
image

渲染

有了渲染书(render),开始渲染:

image

分为四个步骤:

1
2
3
4
1.计算CSS样式
2.构建渲染书
3.布局,主要定位坐标的和大小,是否换行,各种position overflow z-index 属性
4.绘制,将图像绘制出来

然后,图中的线与箭头表示通过 JS 动态修改了 DOM 或者 CSS,会导致页面「重新布局(Layout)」、「渲染(Repaint)」

什么是回流?

Layout,也叫 Reflow。html 的内容。结构、位置或尺寸发送了变化,需要重新计划样式和渲染树

什么是重绘?

Repaint。元素发生的改变只是影响了元素本身的一些外观之类的(背景,边框颜色等),此时只需要应用新样式绘制这个元素就可以了

回流的成本开销>重绘的成本开销,而且一个节点的回流往往导致子节点以及同级节点的回流。

什么会引起回流?

1
2
3
4
5
6
1.页面渲染初始化
2.DOM结构改变,比如删除了某个节点
3.render树变化,比如减少了padding
4.窗口resize
5.获取某些属性
6.改变字体大小

很多浏览器会对回流做优化,会等到数量足够是做一次批处理回流,
但是处理 render 树的直接变化,当获取一些属性的时候,浏览器为了获得正确的值也会触发回流,这样使得浏览器优化无效,包括:

1
2
3
4
5
1.offset(Top/Left/Width/Height)
2.scroll(Top/Left/Width/Height)
3.cilent(Top/Left/Width/Height)
4.width,height
5.调用了getComputedStyle()/IE的currentStyle

回流优化方案

  • 减少逐项更改样式,最好一次性更改 style,或者将样式定义为 Class 并一次性更新
  • 避免循环操作 dom,创建一个 documentFragment 或者 div,在它上面应用所以 DOM 操作,最后把它添加到 window.document 上
  • 避免多次读取 offest 等属性。无法避免则将他们缓存为变量。
  • 将复杂的元素绝对定位或者固定定位,使得他们脱离文档流,否则回流代价会很高

举个栗子:

1
2
3
4
5
6
7
8
9
var s = document.body.style;

s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));

简单层与复杂层

上述中的渲染中止步于绘制,但实际上绘制这一步,需要从简单层和复杂层来讲。

  • 可以默认只有一个复合图层,所有的 DOM 节点都在这个图层上面,
  • 如果开启了硬件加速功能,可以将某个节点转为复合图层
  • 复合涂层之间的绘制互不干扰,由 GPU 控制
  • 而简单图层中,就算是 absolute 等布局,变化的时候不影响整体的回流,但是由于在同一个图层中,仍然是会影响绘制的,因此做动画的时候性能仍然很低,而复合图层是独立的,所以一般动画推荐使用硬件加速。