一、前提
对于一个前端工程师,网页的加载和执行速度一直都是体现前端功底的重要指标之一,而我们在度过最初的实现功能阶段后需要思考如何让自己写的前端代码性能更高效,加载更快。所以学习前端的原理和优化技巧是很有必要的。
在浏览器渲染网页时,会经过一系列步骤来达到最终展示页面的效果,而我们对页面的修改不当会导致页面的重新渲染速度变慢,甚至崩溃。而本节我们将学习浏览器渲染的大致流程以及如何保证渲染的性能。
二、浏览器大致渲染流程
a) 概念:
i. 指的是浏览器从网络上或本地加载网页到页面上显示内容的整个过程
b) 特点:
i. 主要部分是通过浏览器内核来完成,主要参与部分为浏览器渲染引擎和JavaScript解析器
ii. 因为每个浏览器的内核不一致,所以渲染流程大同小异
c) 大致流程,如图1所示:
图1浏览器渲染页面流程图
a) 流程分析
1. 解析HTML文档,构建dom树。
l 当浏览器获取HTML文档时,遍历HTML所有节点并构建成一个dom树。遍历规则是从根节点出发,会在一个节点及所有的子节点都构建完毕,才会构建下一个兄弟节点
2. 解析css样式,生成css 规则树
l 将页面的样式代码通过css解析成样式结构体,在解析的过程中会去掉浏览器不能识别的样式,比如IE会去掉-moz开头的样式,而FF会去掉_开头的样式
3. 将dom树和cssom结合形成render tree(渲染树)
l render tree能识别样式,render tree中每个NODE都有自己的style,而且 render tree不包含隐藏的节点 (比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到 render tree中。注意 visibility:hidden隐藏的元素还是会包含到 render tree中的,因为visibility:hidden 会影响布局(layout),会占有空间。根据CSS2的标准,render tree中的每个节点都称为Box (Box dimensions),理解页面元素为一个具有填充、边距、边框和位置的盒子
4. 利用render tree进行布局计算并显示在页面上
三、什么是重绘和回流
a) 回流(reflow)
i. 概念:
当render tree中的一部分(或全部)会因为元素的规模尺寸,布局,隐藏显示切换等而发生改变,需要重新构建render tree。这就称为回流(reflow)
ii. 理解
每个页面至少需要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树
b) 重绘(repaint)
i. 概念
当render tree中的一些元素需要更新css属性,而这些属性只是影响元素的外观(color、background-color等),风格,而不会影响布局(比如margin、padding等)的。则就叫称为重绘。
四、什么时候触发,有什么影响
a) 何时触发
i. 回流:
1. 加载页面时
2. 用js操作HTML
3. 改变了HTML标签的尺寸
4. 改变了影响布局的css属性,比如margin
5. 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
6. 浏览器窗口大小改变时
ii. 重绘:
1. 回流必定触发重绘
2. 改变了不影响布局的外观css属性,比如color,background-color等。
b) 有什么影响
无论是重绘或者回流都会加重浏览器内核的处理负担,如果回流和重绘次数过多,甚至会让网页崩溃,所以我们有必要学习一些常见的技巧来避免不必要的回流和重绘
五、如何优化
回流和重绘是无法完全避免的,但我们可以减少回流和重绘次数,来提高我们的页面性能
a) 实现动画时,尽量使用transform、opacity、filter等,这些属性会使用显卡(GPU)进行加速,不会引发重绘和回流
b) 在用js操作HTML时,尽量用class先事先定义好样式,然后通过改变className来进行一次性操作。尽量避免一条一条的修改HTML样式\
c) 不要在循环里多次使用dom元素的样式,而是先用一个变量保存样式值,然后用变量替代样式代码。