HTML加载过程
- 要理解回流和重,首先 我们要了解html加载过程中发生了什么下面我们先来分析一下htm加载的过程
- 在页面加载的时候,浏览器会获取到的html代码解析成一个DOM树,DOM树里包含了所有html标签(包含display:none隐藏掉,以及js动态添加的元素)
- 然后浏览器吧所有的样式解析成样式结构体
- 下一步DOM树和样式结构体组合后构建render树(渲染树),render树类似于DOM树,但区别很大,因为render树能够实别样式,render树中每一个节点都有自己的样式,而且render树不包含隐藏的节点,因为这些节点不会用于呈现,而且不会影响页面的呈现,(简单的来说就是DOM树和我们的css样式结合在一起后,渲染出了render树)
下面我们说一下回流和重绘
回流
- 当render树中的一部分(或者全部)因为元素的 规模尺寸,布局,隐藏等改变而需要 重新构建。这就称之为回流。
- 每一个页面至少需要一次的回流(refllow),就是第一次渲染页面的过程。这个时候是一定会发生回流的,因为需要构建render树。在回流的过程中浏览器会使渲染树中受到影响的部分失效并重新构建,完成回流后浏览器会重新绘制收到影响的部分到屏幕中,该过程就是下面我们要说的重绘
重绘
- 当render树中的一些元素需要更新属性,而这些属性只是影响元素的外观而不影响布局的 如背景色。这就叫重绘。
二者之间的区别
- 如果说上面说的两点我们都理解的话,就能很清楚的看出二者之间的区别。我们会发现,在回流的过程中同时也发生了重绘,而在重绘的过程中并不一定会引起回流
- 回流必定引起重绘 儿重绘并不一定会引起回流:像元素的颜色改变时这时候只发生了重绘,并没有引起回流。除了页面的第一次渲染,基本上只有在页面布局和几何属性发生改变时才会引起回流
- 小结:从上面二者之间的区别我们可以看出回流的代价要比重绘高,所以我们在项目开发者 一定要注意回流重绘的问题,做好优化。下面是我总结的五点,但是 远不止并不全,有心的xd感兴趣的话可以自己再去找一下别的优化方案加以补充。
1.避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
2.避免频繁操作DOM,使用文档片段创建一个子树,然后再拷贝到文档中
3.先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘
4.避免循环读取offsetLeft等属性,在循环之前把它们存起来
5.对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流