一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」6的第天,点击查看活动详情。
由于渲染机制过于复杂,所以渲染模块在执行过程中会被划分为很多子阶段,输入的 HTML 经过这些子阶段,最后输出像素。我们把这样的一个处理流程叫做渲染流水线,其大致流程如下图所示:
🐼按照渲染的时间顺序,流水线可分为如下几个子阶段:
- 构建 DOM 树
- 样式计算
- 布局阶段
- 分层
- 绘制
- 分块
- 光栅化
- 合成。
我们可以把渲染流水线当作一个车间流水线,我们只关注输入输出,中间的处理当作黑盒即可;不去关注过程
构建 DOM 树
由于浏览器无法直接理解和使用 HTML,所以需要将 HTML 转换为浏览器能够理解的结构——DOM 树。
HTML解析器:接收到HTML字节流时,首先要经过渲染引擎的HTML解析器,将HTML字节流转换成DOM树结构。
构建 DOM 树的输入内容是一个非常简单的 HTML 文件,然后经由 HTML 解析器解析,最终输出树状结构的 DOM。
可以看到,DOM 和 HTML 内容几乎是一样的,但是和 HTML 不同的是,DOM 是保存在内存中树状结构,可以通过 JavaScript 来查询或修改其内容。
样式计算(Recalculate Style)
已经生成 DOM 树了,但是 DOM 节点的样式我们依然不知道,要让 DOM 节点拥有正确的样式,这就需要样式计算了。
样式计算的目的是为了计算出 DOM 节点中每个元素的具体样式,这个阶段大体可分为三步来完成。
1. 把 CSS 转换为浏览器能够理解的结构
和 HTML 文件一样,浏览器也是无法直接理解这些纯文本的 CSS 样式,所以当渲染引擎接收到 CSS 文本时,会执行一个转换操作,将 CSS 文本转换为浏览器可以理解的结构——styleSheets。
在控制台中输入 document.styleSheets,然后就看到如下图所示的结构:
渲染引擎会把获取到的 CSS 文本全部转换为 styleSheets 结构中的数据,并且该结构同时具备了查询和修改功能,这会为后面的样式操作提供基础。
2. 转换样式表中的属性值,使其标准化
将所有值转换为渲染引擎容易理解的、标准化的计算值,这个过程就是属性值标准化。
3. 计算出 DOM 树中每个节点的具体样式
样式计算阶段的目的是为了计算出 DOM 节点中每个元素的具体样式,在计算过程中需要遵守 CSS 的继承和层叠两个规则。这个阶段最终输出的内容是每个 DOM 节点的样式,并被保存在 ComputedStyle 的结构内
📚CSS 继承
CSS 继承就是每个 DOM 节点都包含有父节点的样式。
📒层叠
层叠是 CSS 的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。它在 CSS 处于核心地位,CSS 的全称“层叠样式表”正是强调了这一点
布局阶段
因为我们还不知道 DOM 元素的几何位置信息。那么接下来就需要计算出 DOM 树中可见元素的几何位置,我们把这个计算过程叫做布局。
Chrome 在布局阶段需要完成两个任务:创建布局树和布局计算。
1. 创建布局树
- 遍历 DOM 树中的所有可见节点,并把这些节点加到布局树中;
- 而不可见的节点会被布局树忽略掉,因为它的属性包含 dispaly:none,所以这个元素也没有被包进布局树。
2. 布局计算
当Webkit创建RenderObject对象之后,每个对象是不知道自己的位置,大小等信息的,WebKit根据盒子模型来计算他的位置,大小等信息,这个过程就是布局计算
布局计算是一个复杂的过程,我简单的可以总结为:界面是由很多很多的框模型组成的,每个框模型是由元素的类型以及display属性决定的。而不同的Box会参与到不同的格式上下文中(Formatting Context),完成布局的计算。