最近在准备面试,感觉好些东西了解,但是了解的深度有限。自己就总结了几个模块,打算强化一下。如果你感觉我的文章对你有帮助,请点赞。如果感觉有哪些不足之处,可以留言。让我们一同进步,学习!!!
最后在说明一下,这个系列我会一直写下去。如果,你有什么好的方向,也可以提出来。
渲染过程
上面这个图的基本流程如下:
1、解析html代码(HTML代码本质是字符串)转化为浏览器认识的节点,生成DOM树,也就是DOM Tree
2、解析css,生成CSSOM(CSS规则树)
3、把DOM Tree 和CSSOM结合,生成Rendering Tree(渲染树)
解析HTML构建DOM树
其实我们第一次拿到的页面HTML是一堆我们看不懂的01,也就是字节流
接着浏览器按照规定的编码格式(常用UTF-8)将他们转换成对应的字符。当前这些内容从字节流变成了字符串。
字符串我们是认识的,浏览器不一定认识。接下来就要进行编译原理中词语解析那个步骤。就是将字符串转换成一个个词,当然了浏览器还是不能识别的。
在上面那个过程进行中,每当一个词被解析出来,就生成一个 Node 节点。并把前后关系,属性之类的配置好。生成最后的 Dom 树。这个步骤经历了编译原理中语法解析那个步骤。
tips:编译原理学的一般的,比如我,在面试中这个部分就不要讲那么细了,简直就是给自己挖坑
解析CSS构建CSSOM树
基本流程和HTML解析过程一样
0/1 -> 编码解析 -> 词法分析 -> 语法分析 -> CSSOM树
看上面的图,我们也能够发现。DOM树的构建过程和CSSOM树的构建过程是同步的。但是无论是谁先结束,都要等待对方。他们要同时进入下一个步骤。
为什么呢?CSS的样式具有继承性。所以在构建过程中,需要递归DOM树为其渲染样式。
所以首页的渲染速度与CSS的加载速度以及以及构建速度有很大关系。
优化,DOM树要少,cs尽量id和class,少这几用标签
解析JavaScript
说起来JS是个很神奇的存在。他可以写在任何地方。但是我们却不是很提倡将他写在HTML。我们都知道HTML,CSS的构建过程走的是GUI渲染线程。而JS走的JS引擎线程。又因为JS可以操作DOM,为了避免无效的节点资源渲染。GUI线程与JS引擎线程是互斥的。这也就是常说的JS会阻塞HTML构建。
因此,我们建议将JS代码放在HTML底部。
我们的目的是为了让用户更早的看到画面。放在中间或者上方都会阻塞DOM树的构建。当然了,也可以使用async或defer的方式加载。
渲染树(Render Tree)
Render Tree 由 DOM数和CSSOM树合并组成。Render Tree 包含了渲染网页所需的节点,用于计算元素的布局,最终输出绘制流程,将像素渲染到屏幕上。
从DOM树的根节点开始遍历每一个可见节点
对于每个节点,找到对应的CSSOM规则并应用
输出可见节点,连同其内容和计算的样式
布局(Layout)
渲染树包含了屏幕上的所有可见内容及其样式信息,接下来就要进入Layout阶段了。大白话说,就是在一个设备上,某个节点到底处于什么位置。在Layout阶段,也称为自动重排或回流(Reflow)。所以说,渲染过程中,最少会发生一次重排。
绘制(Painting)
现在我们已经知道每个节点在什么地方了。接下来就会将每个节点转换成屏幕上的实际像素。进行绘制。绘制过程会出现重绘。也就是说,渲染过程,最少会发生一次重绘。
这个地方可以如此理解,像画画一样。已经打好底图了,线条什么已经勾勒好了,我们按照要求着色就可以了。
重绘(Repaint)
就像这个名一样。重绘,重新绘制的意思。就是基本位置不改变,改过外观样式之类的。背景色,字体颜色,边框等。
还拿画画举个例子,某个地方改变那个颜色不看,又换一种颜色。
回流或重排(Reflow)
回流也叫做重排,一个意思。重排,也是字面意思,重新排列,说明他的位置发生了改变。所以发生在布局(Layout)那个时间范围。又因为布局在时间上早已绘制。所以重排一定会触发重绘。也说明重排的消耗要高于重绘。
引起重排
- 页面初始化
- DOM结构变化
- 窗口大小改变
- render树发生变化
一个核心,只要是改变了布局,就会发生重排
如何减少重绘和重排
-
减少样式更新次数,写到一个class中,一次更新
-
避免循环改变DOM
写到代码片段中 documentFragment 中,直接一次性操作
克隆一个 DOM节点在内存中,修改之后,在替换(有种替换零件的感觉) -
将复杂的元素绝对定位或固定定位,使得它脱离文档流,否则重排代价会很高
-
改变字体也会引起回流,尤其是改变全局字体大小的。
-
拒绝使用table布局
合成(Composite)
前面一个步骤已经将画面绘制完成,接下开就是将绘制的结果发送给GPU(显卡)
总结
渲染过程的总结
- 拿到定于在头部的DTD,确定解析类型
- 将解析后的内容交给GUI渲染
- HTML解析器将字字节流转换为字符流
- 此法分析器解析成词
- 根据语法,组成DOM树
- 记住JS与GUI是互斥的。解析过程中遇到JS,GUI会挂起
- CSS根据相应的规则,生成CSS树
- 合并CSS树与DOM树,生成渲染树
- 对渲染树进行布局和绘制,将结果通过IO线程给Browser进程显示