前言
前段时间,用vue做了一个吸顶等功能,实现这个功能会涉及到监听页面滚动,自然而言就会涉及到读取相关属性,频繁的读取属性,会导致reflow,也就会影响页面的性能,为了后面开发过程中,尽量写出更优的代码,因此总结一下回流和重绘的相关知识点
浏览器的渲染过程
要了解回流和重绘,首先要知道浏览器客户端的渲染过程,主要分为以下步骤:
- 解析HTML生成DOM树
- 解析CSS生成CSSDOM规则树
- 将CSSDOM规则树和DOM树合并成一个Render Tree
- 根据Render Tree来布局,计算每个节点的大小位置信息
- 将Render Tree每个节点绘制到屏幕
什么是回流(reflows)
回流(reflows)是指网络浏览器为了重新渲染部分文档或者全部文档而重新计算文档中元素的位置和几何结构的过程,简单来说,就是页面上某些元素的大小、位置或者显示隐藏等发生改变导致页面重新构建的过程
什么是重绘(repaints)
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
特点:回流必将引起重绘,重绘不一定引起回流 回流比重绘的代价更高
什么会导致回流(reflows)、重绘(repaints)?
以下情况会导致回流:
- 调整浏览器窗口大小
- 元素字体大小变化
- 脚本操作(添加或者删除)DOM(可见的,对display:none的元素进行操作不会引起回流、重绘)
- 元素的位置或者大小变化
- 内容改变引发的尺寸变化,如文本改变(用户在input框中输入文字)或者图片大小改变而引起的宽度和高度改变
- 激活CSS伪类(例如:hover)
- 计算 offsetWidth 和 offsetHeight 属性等
一些常用且会导致回流的属性和方法:
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- scrollIntoView()、scrollIntoViewIfNeeded()、scrollTo
- getComputedStyle()、getBoundingClientRect()
如何避免回流、重绘?
1. css
- 避免使用table布局
在布局完成之前,table经常需要多个关口,因为table可以影响在它之前进入DOM的元素的显示。例如,由于表格的最后的一行内容过长而导致纵列大小的完全改变。另外还有一点就是,即使一些小的变化将导致表格(table)中的所有其他节点回流。 - 牺牲平滑度换取速度
意思是指您可能想每次1像素移动一个动画,但是如果此动画及随后的回流使用了100%的CPU,动画就会看上去是跳动的,因为浏览器正在与更新回流做斗争。动画元素每次移动3像素可能在非常快的机器上看起来平滑度低了,但它不会导致CPU在较慢的机器和移动设备中抖动。 - 将动画效果应用到position属性为absolute或fixed的元素上
他们不会影响其他元素的布局,不会导致回流,性能消耗更低 - 避免使用CSS的JavaScript表达式 (仅 IE 浏览器),如calc()
- 避免设置多项内联样式
通过style属性设置会导致回流,避免设置多项内联样式(不要一个一个改变元素的样式属性),因为每次都会造成回流,样式应该合并在一个外部类(class),直接操作改class,只会产生一次回流 - 尽可能在DOM树的最末端改变class
回流可以自上而下,或自下而上的回流的信息传递给周围的节点。回流是不可避免的,但可以减少其影响。尽可能在DOM树的里面改变class,可以限制了回流的范围,使其影响尽可能少的节点。例如,应该避免通过改变父类去影响子节点的显示。
2. js
- 避免频繁操作DOM,改善DOM操作导致的回流
(1)让要操作的元素进行离线处理(即让元素不存在与Render Tree中),处理完后一起更新- 使用documentFragment进行缓存操作,引发一次回流和重绘(主要用于添加元素,先把所有需要添加的元素添加到一个容器 内,然后再添加到body中)
- 使用display:none 技术(先display:none隐藏元素,然后对元素进行操作,然后显示元素)
- 使用cloneNode(true or false) 和 replaceChild 技术
(2)不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存
(3)不要一个一个改变元素的样式属性,直接改变className,如果动态改变样式,则使用cssText
(4)让元素脱离动画流(应用到position属性为absolute或fixed的元素),减少回流的Render Tree的规模