chrome浏览器在地址栏输入URL到页面展示,这中间发生了什么

2020-06-07  本文已影响0人  山野乔治

距上次的导航流程已有些日子,趁着这次休假把剩下的渲染流程也分享出来。
通过本文可以透视浏览器是如何进行渲染工作的。

众所周知,浏览器传输的相关文件包括 js文件html文件css文件。

//HTMl: 超文本 标记语言
<p>山野乔治</p>
//CSS:层叠样式表 
p { color: red }
//JavaScript
p.style.color = 'gray'  通过页面修改内容

1.html的内容由标记和文本组成,标记也称为标签。每个标签都有自己特定的含义,浏览器会根据不同的语义化的标签来进行渲染不同的内容。比如上面的的<p>标签会告诉浏览器在这里需要创建一个新的段落,中间的文本就是段落要显示的内容。

2.css文件又称为层叠样式表,是由选择器和属性组成。通过css可以改变文字的大小,颜色等信息。图中的p标签,会把设定的属性值,全部应用到p标签上。

3.至于JavaScript,使用这个可以让页面的内容‘动’起来。也就是大部分的用户和浏览器的交互操作,都是通过JavaScript完成的。


搞清楚了HTML,CSS,JavaScript基本含义之后,我们就开始详细了解浏览器的渲染机制吧。

渲染模块在执行过程中会被划分为很多子阶段,输入的HTML经过这些子阶段,最后输出为了像素。我们把这样的一个处理流程就叫做渲染流水线,大致过程如下图所示。

img

按照渲染的时间顺序,流水线可以分为这几个子阶段:

每个阶段的过程中,我们应该重点关注:1,开始每个子阶段都有其输入的内容;2,然后每个子阶段有其处理过程;3,最终子阶段会生成其输出内容。也就是:输入-》加工-》输出

构建DOM树

为什么要构建DOM树呢?

我们浏览器是无法直接理解和使用HTML的(HTML标记语言是为了让开发人员进行编程的语言)所以浏览器需要将转化为浏览器可以理解的结构,那就是---DOM树。

了解过数据结构的开发人员应该都清楚什么是树结构。有一父节点可以有很多个子节点,但一个子节点不能被不同的父节点共享。在我们浏览器的渲染机制中,就频繁的使用到了树结构。

那么DOM树是如何进行构建并进行渲染的呢?

DOM树构建过程.png

在构建DOM树的时候,输入内容就是一个简单的HTML文件,然后由HTML解析器进行解析,最终输出一个树状结构的DOM。

为了能直观的了解什么是DOM结构,可以在控制台上输入document进行查看完整的一个DOM结构。DOM和HTML内容几乎一摸一样的,但是和HTML不同的是,DOM是保存在内存中的树状结构,可以通过JavaScript来查询或修改其内容。如何通过JavaScript来修改DOM的内容呢?控制台输入以下内容

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

这个代码作用就是把第一个P标签的文本内容转换为black。当执行这行代码的时候,DOM的一个p节点的内容成功被修改,同时页面的内容也会被修改。

这就是生成DOM树的过程,此刻DOM节点的样式我们依然不知道,要让DOM拥有正确的样式,就需要进行下一个渲染子进程了。

样式计算(Recalculate Style)

样式计算的目的是为了计算DOM节点中每个元素的具体样式,这个子进程大概需要分为三步来完成。

1.把CSS转化为浏览器能够理解的结构

那么CSS样式的来源主要有哪些呢?

和第一个构建DOM树一样,浏览器也是不能直接理解纯文本的CSS样式,所以当渲染引擎就收到css文件的时候,首先会进行一个转化操作,将css文本转化为浏览器可以理解的结构---styleSheets

同样,想要更要直观的查看styleSheets的结构,我们可以在控制台输入document.styleSheets,就能看到对应的css结构。

styleSheets.png

可以看出,这个样式表包含了很多样式,已经把那三种来源的样式都包含进去了。当然样式表的具体结构在这里不赘述,只介绍渲染引擎会把获取到的CSS文件全部转换为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。这些类型数值都不容易被渲染引擎所理解,所以需要将所有值转换为渲染引擎所能理解的标准化的计算值,这个过程就是属性值标准化。

那么标准化后的属性值是什么呢?

body { font-size: 32px }
p { color: rgb(0,0,255) }
span { display: none }
div { font-weight: 700 }
div p { color: rgb(0,128,0) }
div { color: rgb(255,0,0) )

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 }

那么如何继承呢?如下图所示

css继承.png

所有的子节点都继承了父节点的样式。比如body节点的font-size属性是20,那么body节点下面的所有节点的font-size都等于20。

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

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

如果想要了解每个DOM元素最终的计算样式,可以打开Chrome的“开发者工具,选择一个element标签,然后再选择“Computer”子标签。

computer中存储最终计算的样式.png

在进行计算之后,我们就进行布局阶段。

布局阶段

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

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

1.创建布局树

你可能注意到了DOM树还含有很多不可见的元素,比如head标签,还有使用了display:none属性的元素。所以在显示之前,我们还要额外地构建一棵只包含可见元素布局树。

我们结合下图来看看布局树的构造过程:

布局树构造过程.png

从上图可以看出,DOM树中所有不可见的节点都没有包含到布局树中。

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

2.布局计算

现在我们有了一棵完整的布局树。那么接下来,就要计算布局树节点的坐标位置了。布局的计算过程非常复杂,等到后续详解。

在执行布局操作的时候,会把布局计算的结果重新写会布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开。对于这个问题,Chrome团队正在重构布局代码,下一代布局系统叫做LayoutNG,试图分离输入和输出,从而让布局算法更加简单。

综上本问介绍了渲染进程的三个子进程:DOM生成,样式计算和布局。

总结:

子过程比较多,小伙伴迫切叫我健身。渲染进程那就先到这里了,剩下的进程我们下节再叙~

上一篇 下一篇

猜你喜欢

热点阅读