在我之前的文章《面试常见问题》中,我概述了浏览器渲染过程,这次我将更详细地解释这部分内容。
很多前端开发人员通常专注于业务开发,可能对浏览器渲染阶段了解不多。其实这个阶段非常重要。了解浏览器渲染过程将帮助您了解您编写的HTML、CSS 和JS 代码是如何解析并最终渲染在页面上的。对于页面性能的优化,也有相应的解决方案。
我们先来看问题。
HTML、CSS、JS文件是如何在浏览器中转换成页面的?
如果您无法回答,请继续阅读。
根据渲染的时间顺序,渲染过程可以分为几个子阶段:DOM树构建、样式计算、布局阶段、分层、光栅化和合成显示。
让我们仔细看看每个阶段会发生什么。
1. 构建DOM树
HTML文档描述了页面的结构,但由于浏览器无法直接理解和使用HTML,因此必须通过HTML解析器将HTML转换为浏览器可以理解的结构化——DOM树。
HTML文档中的所有内容都是一个节点,每个节点都有层次关系,相互连接形成一棵DOM树。
构建过程:读取HTML文档的字节,将字节转换为字符(Char),根据字符确定标签(token),将标签转换为节点(node),根据节点构建DOM树来做。参见下图。
打开Chrome的开发者工具,在控制台中输入您的文档,然后按Enter键即可看到完整的DOM树结构,如下所示。
打印到控制台的DOM 结构与HTML 内容类似,但与HTML 不同的是,DOM 是存储在内存中的树结构,可以通过JavaScript 查询或修改其内容。
2. 样式计算
此阶段的样式计算计算DOM 节点内每个元素的表现样式。
2.1 解析CSS
CSS样式可以通过三种方式引入:
通过链接引用外部CSS 文件的样式标记内CSS 元素的样式属性中的嵌入CSS 与HTML 中相同。浏览器必须将CSS 解析为样式表。通过CSS 解析器进行结构。这通常称为CSSOM 树。
styleSheets结构还具有查询和修改功能。
document.styleSheets
2.2 属性值标准化
理解属性值标准化的字面意思有点困难,但是让我们看看下面的例子来了解什么是属性值标准化:Sho。
在编写CSS样式时,在设置颜色属性值时,常见的是使用白色或红色等颜色,但这样的值对于浏览器的渲染引擎来说很难理解,因此所有值都需要进行转换。渲染引擎更容易理解的标准化计算值。这个过程就是属性值的标准化。
白色的归一化值为rgb(255, 255, 255)。
2.3 计算DOM树中每个节点的样式
标准化样式属性值后,您需要计算每个节点的样式属性。在这个阶段你需要了解两个CSS 规则:
继承规则:每个DOM节点都包含其父节点的样式。 级联规则:级联是一种定义如何组合来自多个源的属性值的算法。样式计算阶段计算DOM 节点中每个元素的特定样式。在计算过程中,必须遵循两个规则:CSS继承和级联。
此阶段的最终输出是每个DOM 节点的样式,存储在ComputedStyle 结构中。
3. 布局阶段
完成上述两个步骤后,您将拥有一个DOM 树以及DOM 树中元素的样式。接下来,我们需要计算DOM 树中可见元素的几何位置。这个计算过程就是一个布局。
3.1 创建布局树
DOM树包含一些隐藏元素,例如head标签、带有display:none属性的元素,因此需要额外构建一个仅包含可见元素的布局树。
构建过程:从DOM树的根节点开始,将所有可见节点添加到布局树中,并忽略隐藏节点。
3.2 布局计算
现在布局树已构建完毕,您可以开始计算布局树节点的坐标位置。从根节点开始遍历,结合上面计算出的样式,确定页面上每个节点对象的具体大小和位置,并将这些信息存储在布局树中。
布局阶段的输出是一个盒模型,它准确地捕获屏幕上每个元素的确切位置和大小。
4. 分层
现在您已经有了布局树并知道了每个元素的具体位置信息,您可能需要执行3D 转换、滚动页面或使用Z 索引对Z 轴重新排序。为了更方便地实现这些复杂的效果,渲染引擎还应该为特定的节点生成专用的图层以及相应的图层树(LayerTree)。
您可以通过打开Chrome 浏览器中的开发人员工具并选择“Elements-Layers”选项卡来查看页面分层,如下图所示。
浏览器页面实际上分为很多层,这些层层叠在一起组成最终页面。
至此,两棵树已经构建完毕:布局树和图层树。我们来看看这两棵树之间的关系。
在正常情况下,布局树中并非所有节点都包含层。如果某个节点没有对应的层,则该节点从属于父节点的层。
节点必须满足什么条件才能晋升到另一层?只要满足以下条件之一:
具有堆叠上下文属性的元素将提升为单独的图层,并且还会在需要剪切的地方创建图层。
5. 图层绘制
构建图层树后,渲染引擎绘制图层树中的每个图层。
渲染引擎在实现图层绘制时,会将图层的绘制划分为许多更小的绘制指令,这些指令又形成一个绘制列表。
6. 栅格化(raster)操作
绘制图层会生成绘图列表。这是一个用于记录绘图顺序和绘图指令的列表。实际上,绘制操作是由渲染引擎的合成线程完成的。
我们看看下图渲染主线程和合成线程的关系。
当图层的绘制列表准备好后,主线程将绘制列表发送到合成线程,合成线程开始工作。
首先,合成线程将图层分割成图块。切片大小通常为256256 或512512。
然后,合成线程根据视口附近的图块优化位图。生成位图的实际操作是通过光栅化来执行的。光栅化是指将图块转换为位图。瓦片是光栅化的最小单位。渲染过程维护一个光栅化线程池,并执行所有图块的光栅化,如下图所示。
7. 合成和显示
一旦所有图块都被光栅化,合成线程就会生成命令——“DrawQuad”来绘制图块,并将该命令发送到浏览器进程。
浏览器进程有一个名为viz 的组件,它接收从合成线程发送的DrawQuad 命令并相应地执行它们。 DrawQuad命令将页面内容绘制到内存中,最后将内存显示在屏幕上。
对于多年开发经验丰富的程序员的好处:从网页创建、网站开发、Web前端开发、HTML+CSS+JavaScript等基础知识开始。任何需要真实移动小程序项目【视频+工具+电子书+系统路线图】的伙伴,包括jQuery、Vue、React、Ajax、node、Angular框架等,都可以一起发给我。如果您发送私人消息,发送“前端”并等待3 秒钟,您将获得一个集合地址,并且可以将其提供给任何对编程感兴趣的人。
8. 总结
完整的渲染流程可以总结如下。
1.渲染过程将HTML内容转换为浏览器可以理解的DOM树结构。 2.渲染引擎将CSS样式表转换为浏览器理解的样式表,并计算DOM节点的样式。 3. 创建布局树并计算所需元素的布局信息。 4、对布局树进行层次化,生成层次树。 5. 为每个图层生成绘图列表并将其发送到合成线程。 6. 合成线程将图层分割为图块,并将图块光栅化为位图。 7. 合成线程将图块绘制命令发送到浏览器进程。浏览器进程根据指令生成页面并显示在显示器上。在渲染过程中经常听到的两个概念是回流和重绘。本文不详细介绍,下一篇文章会详细讲解。
版权声明:本文由今日头条转载,如有侵犯您的版权,请联系本站编辑删除。