将html代码转换为页面,渲染进程将HTML转换为页面全流程

HTML转换为页面,其实就是HTML、CSS、JavaScript通过中间渲染模块的处理,

最终输出为页面。

HTML、CSS和JavaScript的含义:

![HTML、CSS和JavaScript](https://img2018.cnblogs.com/blog/1141454/201912/1141454-20191225154714684-1176554809.jpg)

**HTML,超文本标记语言,由标记和文本组成**。标记也称为**标签**,每个标签都有它

的语意,浏览器会根据标签的语意来正确展示HTML内容。

**CSS,层叠样式表,由选择器和属性组成**,通过CSS可以改变HTML的字体颜色,大小等信息。

**JavaScript,一种应用于web端的轻量级,解释型或即时编译型的编程语言**。一般会作为

页面脚本,实现页面动态效果。

了解了HTML、CSS、JavaScript后,我们开始分析渲染模块。

渲染模块在执行过程中会被划分为很多子阶段,输入的HTML经过子阶段最后输出

像素,这样的一个处理流程叫**渲染流水线**。

渲染流水线示意图:

![渲染流水线](https://img2018.cnblogs.com/blog/1141454/201912/1141454-20191225154714942-142555304.jpg)

按照渲染的时间顺序,流水线可分为:**构建DOM树、样式计算、布局阶段、分层、绘制、

分块、光栅化和合成**。

## 构建DOM树

**由于浏览器无法直接解析HTML,所以需要将HTML转换为浏览器能够理解的结构,DOM树**。

树结构类似于生活中的“树”,其中每个点称为**节点**,相连的节点称为**父子节点**。

DOM树构建过程示意图:

![DOM树构建过程](https://img2018.cnblogs.com/blog/1141454/201912/1141454-20191225154715165-1260283092.jpg)

构建DOM树的输入内容是一个HTML文件,然后经过HTML解析器解析,最终输出树状结构的DOM。

通过“开发者工具”->“Console”控制台,输出“document”回车后可查看完整的DOM树结构。

可以了解到,DOM和HTML内容几乎是一样的,但是和HTML不同的是,DOM是保持在内存中树状结构,

可以通过JavaScript来查询和修改内容。

而要让DOM节点拥有正确的样式,需要样式计算。

## 样式计算

样式计算的目的是为了计算出DOM节点中每个元素的具体样式,该阶段可分成三步:

### 1、把CSS转换为浏览器能够解析的结构

HTML加载CSS的三种方式:

![HTML加载CSS的三种方式](https://img2018.cnblogs.com/blog/1141454/201912/1141454-20191225154715519-1721273838.jpg)

CSS样式主要由三种加载方式:

* 通过link引用的外部CSS文件

*

所以元素有了层叠上下文的属性或者需要被剪裁,那么就会被提升成为单独一层,你可以参看下图:

从上图我们可以看到,document层上有A和B层,而B层之上又有两个图层。这些图层组织在一起也是一颗树状结构。

图层树是基于布局树来创建的,为了找出哪些元素需要在哪些层中,渲染引擎会遍历布局树来创建层树(Update LayerTree)。

```

例如所示,文字所显示的区域超过了200*200的显示范围时就产生了剪裁,渲染引擎会把剪裁文字内容

的一部分用于显示在div区域。

出现这种剪裁情况下,渲染引擎会为文字部分单独创建一个层,如果出现滚动条,滚动条也会

被提升为单独的层。

被裁剪的内容所在单独图层的示意图:

![被裁剪的内容所在单独图层的示意图](/chrome/draw13.png)

所以,**元素有了层叠上下文的属性或者需要被检查,满足任意一点,就会被提升为单独的一层**。

## 图层绘制

在完成图层树的构建后,渲染引擎会对图层树中的每个图层进行绘制,渲染引擎会把每个图层的

绘制拆分成很多小的绘制指令,然后再把这些指令按照顺序组成一个待绘制列表。

绘制列表:

![绘制列表](/chrome/draw14.png)

绘制列表中的指令其实就是让其执行一个简单的绘制操作,而每个原生的背景、边框等都需要单独

的指令绘制,通过几条绘制指令来实现绘制一个元素。

“开发者工具”->“Layers”可查看“document”层等的绘制列表过程:

![一个图层的绘制列表](/chrome/draw15.png)

## 栅格化操作

绘制列表只是用来记录绘制顺序和绘制指令的列表,实际上绘制操作是由渲染引擎

中的合成线程来完成的。

渲染进程中的合成线程和主线程:

![渲染进程中的合成线程和主线程](/chrome/draw16.png)

当图层的绘制列表准备完成后,主线程会把该绘制列表提交给合成线程。

通常一个页面很大,而用户有时只能看到其中一部分,所以屏幕上页面的可见区域叫视口(ViewPort)。

这种情况下,要绘制出所有图层内容的话产生的开销太多,所以,**合成线程会将图层划分为图块(title)**,

这些图片的大小通常是256*256或512*512。

图层图块示意图:

![图层划分为图块示意图](/chrome/draw17.png)

**合成线程会按照视口附件的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。

所谓栅格化,是指将图块转换为位图**。而图块是栅格化执行的最小单位。渲染进程

维护了一个栅格化的线程池,所以的图块栅格化都是在线程池内执行的。

合成线程提交图块给栅格化线程池:

![合成线程提交图块给栅格化线程池](/chrome/draw18.png)

通常,栅格化过程都会使用GPU来加速生成,使用GPU生成位图的过程叫快速栅格化或者

GPU栅格化,渲染进程会把生成图块的指令发送给GPU进程,然后在

GPU进程中执行生成图块的位图,生成的位图被保存在GPU内存中。

GPU栅格化:

![GPU栅格化](/chrome/draw19.png)

## 合成和显示

所有图块都被栅格化,合成线程就会生成一个绘制图块的命令,“DrawQuad”,然后

将该命令提交给浏览器进程。

浏览器进程里面有一个叫viz的组件,用来接收合成线程发过来的DrawQuad命令,然后根据

DrawQuad命令将其页面内容绘制到内存中,最后将内存显示在屏幕上。

## 总结

完整的渲染流水线:

![完整的渲染流水线](/chrome/draw20.png)

综上,一个完整的渲染流程为:

1、渲染进程将HTML内容转换为浏览器能识别的**DOM树**结构。

2、渲染引擎将CSS样式表转化为浏览器可以理解的**styleSheets**,计算出

DOM节点的样式。

3、创建**布局树**,并计算元素的布局信息。

4、对布局树进行分层,并生成**分层树**。

5、为每个图层生成**绘制列表**,并将其提交给合成线程。

6、合成线程将图层分成**图块**,并在**栅格化线程池**中将图块转换成位图。

7、合成线程发送绘制图块命令**DrawQuad**给浏览器进程。

8、浏览器进程根据DrawQuad消息生成页面,并显示到显示器上。

## 推荐阅读

HTML标签:[w3school](https://www.w3school.com.cn/html/html_primary.asp)

CSS:[w3school](https://www.w3school.com.cn/css/index.asp)

JavaScript:[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)

层叠上下文属性:[https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context](https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context)

> 文章优先发布于公众号[前端美食汇],关注公众号获取最新内容吧~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值