mirror of
https://github.com/qianguyihao/Web.git
synced 2024-11-01 13:34:46 +08:00
218 lines
8.0 KiB
Markdown
218 lines
8.0 KiB
Markdown
---
|
||
title: 02-浏览器渲染机制
|
||
publish: true
|
||
---
|
||
|
||
<ArticleTopAd></ArticleTopAd>
|
||
|
||
|
||
|
||
|
||
|
||
## 前言
|
||
|
||
**渲染机制**包括的内容:
|
||
|
||
- 什么是DOCTYPE及作用
|
||
|
||
- 浏览器渲染过程。面试经常会问:在浏览器中输入url,发生了哪些事情。其中有一部就是浏览器的渲染过程。
|
||
|
||
- Reflow:重排。面试官问完了渲染机制,一般会紧接着问重排Reflow,你可千万别说你没听过。
|
||
|
||
- Repaint:重绘
|
||
|
||
- Layout:布局。这里的Layout指的是浏览器的Layout。
|
||
|
||
## 什么是DOCTYPE及作用
|
||
|
||
### 定义
|
||
|
||
**DTD**(Document Type Definition):文档类型定义。
|
||
|
||
是一系列的语法规则,用来定义XML或者(X)HTML文件类型。**浏览器会使用DTD来判断文本类型**,决定使用何种协议来解析,以及切换浏览器模式。(说白了就是:DTD就是告诉浏览器,我是什么文档类型,你要用什么协议来解析我)
|
||
|
||
**DOCTYPE**:用来声明DTD规范。
|
||
|
||
一个主要的用途便是文件的合法性验证。如果文件代码不合法,那么浏览器解析时便会出现一些差错。(说白了,DOCTYPE就是用来声明DTD的)
|
||
|
||
|
||
### 常见的DOCTYPE声明有几种
|
||
|
||
> 面试官紧接着会问,常见的 DOCTYPE 有哪些,以及 HTML5 的 DOCTYPE 怎么写。
|
||
|
||
1、**HTML 4.01 Strict**:(严格的)
|
||
|
||
```html
|
||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||
```
|
||
|
||
PS:该DTD包含所有的HTML元素和属性,但不包括展示性的和弃用的元素(比如 font、u下划线等,这些是被废弃了的)。
|
||
|
||
2、**HTML 4.01 Transitional**:(传统的)
|
||
|
||
```html
|
||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
|
||
```
|
||
|
||
PS:该DTD包含所有的HTML元素和属性,但包括展示性的和弃用的元素(比如 font、u下划线等)。
|
||
|
||
|
||
3、HTML 5:
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
```
|
||
|
||
|
||
**总结:**
|
||
|
||
面试时,不会让你写出 HTML 4.01的写法,因为大家都记不住。但是要记住 HTML 5 的写法,别看它简单,知道的人还真不多。
|
||
|
||
面试时,可以这样回答: HTML 4.01 中有两种写法,一种是严格的,一种是传统的;并且答出二者的区别。 HTML 5的写法是`<!DOCTYPE html>`。
|
||
|
||
|
||
|
||
|
||
## 浏览器的渲染过程
|
||
|
||
|
||
|
||
### 渲染树
|
||
|
||
![](http://img.smyhvae.com/20210118-2005.png)
|
||
|
||
> 上方图片的来源:[Google 官方 | 渲染树构建、布局及绘制](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=zh-cn)
|
||
|
||
**渲染树**包含了网页中有哪些节点、节点的从属关系、以及节点的CSS样式(大小、颜色等)。
|
||
|
||
浏览器下载完html文档之后,第一步是先将其解析成文本。而html标签是由一对一对的尖括号表述的,可以被浏览器解析为有含义的标记。这些标记被翻译成节点对象,存放到链型数据结构中。这些节点被称之为**DOM对象**,这个链型数据结构就是**渲染树**。
|
||
|
||
### 渲染过程(重要)
|
||
|
||
浏览器的渲染过程非常复杂,面试时找重点说就行,不然太耗时间。如何快速简洁地描述清楚,是关键。来看看下面这张图。
|
||
|
||
![](http://img.smyhvae.com/20180310_1257.png)
|
||
|
||
渲染过程中,涉及到以下几个概念:
|
||
|
||
- DOM树(DOM Tree):浏览器将HTML标签解析成树形的数据结构。DOM树包含了有哪些节点,以及节点之间的从属关系(嵌套关系)。
|
||
|
||
- CSSOM(CSS Rule Tree):浏览器将CSS解析成树形的数据结构。CSSOM包含了节点的CSS样式(大小、颜色等)。
|
||
|
||
- 渲染树(Render Tree): DOM 树与 CSSOM 树**合并**后形成渲染树。渲染树只包含渲染网页所需的节点(但并不知道位置)。
|
||
|
||
- 布局(Layout): 计算出每个节点在屏幕中的**位置和大小**。
|
||
|
||
- 绘制(Painting):按照算出来的规则,通过显卡,把内容画出来。
|
||
|
||
- composite:合成。浏览器在绘制的时候,一开始不会把所有的内容都画在同一层上。需要把这些内容画在不同的曾上,最终合并到一起,并显示在屏幕上。
|
||
|
||
参考链接:
|
||
|
||
- [浏览器渲染原理及流程](http://www.cnblogs.com/slly/p/6640761.html)
|
||
|
||
### 关键渲染路径
|
||
|
||
说到渲染,就不得不提到“关键渲染路径”,它描述的是渲染从触发到绘制的过程。浏览器渲染经历了五个阶段:
|
||
|
||
> JavaScript/CSS --> Style --> Layout --> Paint --> Composite
|
||
|
||
![](http://img.smyhvae.com/20210118-1950.jpg)
|
||
|
||
> 上方图片的来源:<https://developers.google.com/web/fundamentals/performance/rendering>
|
||
|
||
关键渲染路径描述的是渲染从触发到绘制的全过程,一共经历了五个阶段:
|
||
|
||
(1)**触发视觉的变化:**通过JS、CSS代码来**触发**页面上的视觉变化。比如通过 jQuery添加节点、通过CSS添加动画,都可以触发视觉上的变化。
|
||
|
||
(2)Style:浏览器对样式进行计算。匹配选择器,计算哪些CSS受到了影响。
|
||
|
||
(3)layout:同上一段。
|
||
|
||
(4)painting:同上一段。
|
||
|
||
(5)conmposite:同上一段。
|
||
|
||
理论上,上面的五个步骤都是必须要经历的。布局和绘制是关键渲染路径中,最重要、开销最高的两个步骤。
|
||
|
||
但是,有些样式并不会影响布局,也不会影响绘制。所以,浏览器对这方面的性能进行了优化,并不一定要经历布局和绘制这两个过程。这就需要我们先了解一下「重排」和「重绘」这两个概念。详见下一段。
|
||
|
||
|
||
|
||
|
||
|
||
## 布局/回流/重排
|
||
|
||
### 定义
|
||
|
||
布局 layout:
|
||
|
||
渲染对象在创建完成并添加到渲染树时,是将DOM节点和它对应的样式结合起来,并不包含位置和大小信息。
|
||
|
||
我们还需要通过 `Layout` 布局阶段,来计算它们在设备视口(viewport)内的确切位置和大小,计算这些值的过程称为`回流`、`布局`或`重排(Reflow)`。
|
||
|
||
|
||
|
||
参考链接:
|
||
|
||
- [从浏览器渲染原理,浅谈回流重绘与性能优化](https://www.cnblogs.com/xiahj/p/11777786.html)
|
||
|
||
- [你真的了解回流和重绘吗](https://github.com/chenjigeng/blog/issues/4)
|
||
|
||
### 什么时候会触发布局
|
||
|
||
DOM元素的**大小**和**位置**发生变化的时候,会触发布局。
|
||
|
||
- 增加、删除DOM元素
|
||
|
||
- display: none
|
||
|
||
- 移动元素位置,或是增加动画
|
||
|
||
- 修改CSS样式时(宽高、display 为none等,都是通过css样式来修改的)
|
||
|
||
- offsetLeft、scrollTop、clientWidth
|
||
|
||
- 修改浏览器窗口大小时(即Resize窗口,移动端没有这个问题),或是滚动的时候,**有可能**会触发(具体要看浏览器的规则)。
|
||
|
||
- 修改网页的默认字体时(这个很消耗性能)。
|
||
|
||
**面试总结:**
|
||
|
||
首先要答出 Reflow 定义;其次,什么时候触发,至少要答出两条。更进一步,面试官可能还会问你**怎么避免reflow**,这个可以自己去查查。
|
||
|
||
|
||
|
||
## 绘制/重绘
|
||
|
||
### 定义
|
||
|
||
**绘制 paint**:当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器便把这些元素都按照各自的特性绘制一遍,于是页面的内容出现了,这个过程也称之为 Repaint(重绘制)。
|
||
|
||
说白了,页面要呈现的内容,统统画在屏幕上,这就叫 Repaint。
|
||
|
||
### 什么时候触发绘制
|
||
|
||
- DOM改动
|
||
|
||
- CSS改动
|
||
|
||
其实,就是判断当视觉上是否发生变化(无论这个变化是通过DOM改动还是CSS改动)。只要页面显示的内容不一样了,肯定要 Repaint。
|
||
|
||
**面试总结:**
|
||
|
||
面试官经常会问:“如何**尽量减少**Repaint的频率?”
|
||
|
||
注意, reflow是问“怎么避免”,repaint是问“怎么减少”。Repaint是无法避免的,否则就成了静态页面了。
|
||
|
||
**答案**:
|
||
|
||
(1)如果需要创建多个DOM节点,可以使用**DocumentFragment**创建完,然后一次性地加入document。(加一个节点,就repaint一次,不太好)
|
||
|
||
(2)将元素的display设置为”none”,完成修改后再把display修改为原来的值。
|
||
|
||
参考链接:[如何减少浏览器repaint和reflow ?](http://blog.csdn.net/liaozhongping/article/details/47057889)
|
||
|
||
|