浅析Chrome的渲染流程(上)

通常,我们编好了HTML、CSS、JavaScript等文件,经过浏览器就会显示出漂亮的页面,但是浏览器是怎么将它们转化成页面的呢?有兴趣的朋友请往下看。

HTML、CSS、JavaScript是什么

首先我们看下面的图:
在这里插入图片描述
从图中可以看出,HTML的内容是由标记和文本组成。标记也称为标签,每个标签都有它自己的语义(div、span除外),浏览器会根据标签的语义来正确展示HTML内容。比如上面的<p>标签是告诉浏览器在这里的内容需要创建一个段落,中间的文本就是段落中需要显示的内容。

如果需要改变HTML的字体颜色、大小等信息,就需要用到CSS。CSS又称为层叠样式表,是由选择器和属性组成,比如图中的p选择器,它会把HTML里面的<p>标签的内容选择出来,然后再把选择器的属性值应用到<p>标签内容上。选择器里面有个color属性,它的值是red,这是告诉浏览器引擎把<p>标签的内容显示红色。

JavaScript(简称JS),使用它可以让网页的内容 “动” 起来,比如上图中,可以通过JavaScript来修改CSS样式值,从而达到修改文本颜色的目的。

由于渲染机制过于复杂,所以渲染模块在执行过程中会被划分为很多子阶段,输入HTML经过这些子阶段,最后输出像素(一张位图)。我们把这样的一个处理流程叫做渲染流水线,其大致流程如下图所示:
在这里插入图片描述
按照渲染的时间顺序,流水线可以划分如下几个阶段:构建DOM树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成。

构建DOM树

为什么要构建DOM树呢?这是因为浏览器无法直接理解和使用HTML,所以需要将HTML转换为浏览器能够理解的结构-DOM树。

DOM树的构建过程,可以参考下图:
在这里插入图片描述
从图中可以看出,构建DOM树的输入内容是一个非常简单的HTML文件,然后经由HTML解析器解析,最终输入树状结构的DOM。

你可以在Chrome的 “开发者工具” 中,选择 “Console” 标签来打开控制台,然后在控制台里面输入 “document” 后回车,这样你就能看到一个完整的DOM结构了,如下图所示:
在这里插入图片描述
图中的doucment就是DOM结构,你可以看到,DOM和HTML内容几乎是一样的。但是和HTML不同的是,DOM是保存在内存中树状结构,可以通过JavaScript来查询和修改其内容。

那我们如何通过JavaScript代码来修改DOM结构呢?在控制台中输入以下内容:

document.getElementsByTagName("p")[0].innerText = "black"

这句代码的作用是把第一个p标签的内容的修改为black,具体的执行结果可以参考下图:
在这里插入图片描述
从图中可以看到,在执行了一段修改第一个p标签的JavaScript代码后,DOM的第一个p节点的内容成功被修改,同时页面的内容也被修改了。

样式计算

这个阶段可以分为三个步骤来完成。

1.把CSS转换成浏览器能够理解的结构

CSS的来源有三种:

  • 通过link引用外部的CSS文件
  • <style>标记内的CSS
  • 元素的style属性内嵌的CSS

如下图所示:

在这里插入图片描述
和HTML一样,浏览器也是无法直接理解这些纯文本的CSS样式,所以当渲染引擎接收到CSS文本时,会执行一个转换操作,将CSS文本转换为浏览器可以理解的结构——styleSheets

你可以在Chrome “开发者工具中” 的 “Console” 中输入document.styleSheets,就可以看到如下图所示的内容:

在这里插入图片描述
从图中可以看到,这个样式表包含了很多中样式,已经把那三种来源的样式都包含进去了。

2.转换样式表中的属性值,使其标准化

现在我们已经把现有的CSS文本转换为浏览器可以理解的结构了,那么接下来就要对其进行属性值的标准化操作

首先看下面的代码:

body { font-size: 2em }
p {color:blue;}
span  {display: none}
div {font-weight: bold}
div  p {color:green;}
div {color:red; }

可以看到上面的CSS文本中有很多的属性值,如2em、blue、bold,这些类型值不容易被渲染引擎理解,所以需要将所有值转换为渲染引擎容易理解的、标准化的计算值,这个过程就是属性值标准化。
在这里插入图片描述
从图中可以看到,2em被解析成了 32px, red被解析成了 rgb(255,0,0), bold被解析成了700…

3.计算出DOM树中每个节点的具体样式

现在样式的属性值已经被标准化了,接下来就需要计算DOM树中每个节点的样式属性了,如何计算呢?

这就涉及到CSS的继承规则和层叠样式了。

首先是CSS继承。CSS继承就是每个DOM节点都包含父节点的样式。我们结合具体例子来说明一下:

body { font-size: 20px }
p {color:blue;}
span  {display: none}
div {font-weight: bold;color:red}
div  p {color:green;}

这张样式表最终应用到DOM节点上的效果如下图所示:
在这里插入图片描述
从图中可以看出,所有子节点都继承了父节点样式。比如body节点的font-size属性是20,那body节点下面的所有节点的font-size都等于20。

我们可以在Chrome “开发者工具” 的"element" 标签中,选择 “style” 子标签,可以看到如下的界面:
在这里插入图片描述
这个界面展示的信息很丰富,大致可描述如下:

  • 首先,可以选择要查看的元素的样式(位于图中的区域2中),在图中的第一个区域中点击对应的元素,就可以在下面区域看到要查看的样式了。比如这里我们选择的元素时p标签,位于html.body.div.这个路径下面。
  • 其次,可以从样式来源(位于图中的区域3中)中查看样式的具体来源信息,看看是来源于样式文件,还是来源于UserAgent样式表,它是浏览器提供的一组默认样式,如果你不提供任何样式,默认使用的就是UserAgent样式
  • 最后,可以通过区域2和区域3来查看样式继承的具体过程。

以上就是CSS继承的一些特性,样式计算过程中,会根据DOM节点的继承关系来合理计算节点样式。

样式计算中的第二个规则是样式层叠。层叠是CSS的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法它在CSS处于核心地位,CSS的全称 “层叠样式表” 正是强调了这一点

总之,样式计算阶段的目的就是为了计算出每个元素的具体样式,在计算过程中需要遵守CSS的继承和层叠两个规则。这个阶段最终输出的内容是每个DOM节点的样式,并被保存在ComputedStyle的结构中。

如果想了解每个DOM元素最终的计算样式,可以打开Chrome “开发者工具” 中的 "element"标签, 然后再选择 “Computed” 子标签,如下图所示:
在这里插入图片描述
上图红色方框中显示了html.body.div.p标签的ComputedStyle的值。

布局阶段

现在,我们有了DOM和DOM树中元素的样式,但这还不足以显示页面,因为我们还不知道DOM元素的几何位置信息。那么接下来就需要计算出DOM树中可见元素的几何位置,我们把这个计算过程叫作布局

Chrome在布局阶段需要完成两个任务:创建布局树和布局计算。

1.创建布局树

由于DOM中含有很多不可见的元素,比如head标签,还有使用了display:none属性的元素。所以在显示之前,还要额外地构建一颗只包含可见元素的布局树。

我们结合下图来看看布局树的构造过程:
在这里插入图片描述
从上图可以看出,DOM树中的所有不可见的节点都没有包含到布局树中。

为了构建布局树,浏览器大体上完成了下面的这些工作:

  • 遍历DOM树中的所有可见节点,并把这些节点加到布局树中。
  • 而不可见的节点会被布局树忽略掉,如head标签下面的全部内容,再比如body.p.span这个元素,因为它的属性包含display:none,所以这个元素也没有被包含在布局树中。

2.布局计算

现在我们有了一颗完整的布局树。那么接下来,就要计算布局节点的位置了。

在执行布局操作的时候,会把布局运算的结构重新协会布局树中,所以布局树既是输入内容,也是输出内容,这是布局阶段一个不合理的地方,因为布局阶段并没有清晰地将输入内容和输出内容区分开来。

今天就讲这么多,感兴趣的朋友可以留意我后面的文章。

发布了10 篇原创文章 · 获赞 0 · 访问量 120

猜你喜欢

转载自blog.csdn.net/weixin_42071117/article/details/104702947
今日推荐