- repaint(重绘):指的是一种,不会影响当前DOM结构和布局的一种重绘动作。
- reflow (回流): 要发生在DOM树被操作的时候,任何改变DOM结构和布局,都会产生Reflow。一个元素的reflow操作发生时,它的所有的父元素和子元素都会发生reflow,最后reflow必然会导致repaint的发生;
严重性:
- 在性能优化的前提下,reflow的性能消耗要比repaint的大。
体现:
- repaint是某个DOM元素进行重绘,reflow是整个页面进行重排,也就是对页面所有的DOM元素渲染。
如何触发?
repaint的触发:
1. 不可见到可见(visibility样式属性);
2. 颜色或图片的变化(background, border-color, color 样式属性;
3. text-aligin, a:hover 也会造成重绘;
4. 伪类引起的颜色变化不会导致页面回流,仅仅会触发重绘,不改变页面元素大小,形状和位置,但改变其外观。-
reflow的触发:
1. 浏览器窗口的变化;
2. DOM节点的添加和删除操作;
3. 一些改变页面元素的大小,形状,位置的操作会触发;
4. DOM元素测量属性和方法也会触发reflow,如下:
```
var tipWidth = tipBox.offsetWidth;//reflow
tipScrollLeft = tipBox.scrollLeft;//reflow
display=window.getComputedStyle(div,'').getPropertyValue('display');//reflow```
如何尽量避免reflow?
- 尽可能在DOM末梢,通过设置class来修改DOM元素的style属性,尽可能减少受影响的DOM元素。
- 避免设置多项内联样式,使用常用的class方式进行样式设置,以避免设置样式时,访问DOM的低效率。
- 设置动画元素position属性值为fixed 或 absolute,这样当前动画元素由于从当前文档流中脱离出来,因此受影响的只有当前元素。
- 牺牲精度,满足性能:动画精度太强,会造成更多的repaint/reflow,牺牲精度,能满足性能的损耗,获取性能和动画平滑度的平衡。
- 避免使用table进行布局,table每个元素的大小以及内容的改变,都会造成整个table进行重新计算,造成大幅度的repaint和reflow, 改用div则可以针对性的进行repaint 和 避免不必要的reflow 。
- 避免在CSS中使用运算式。
通过 Reflow 和 Repaint 的介绍可知,每次 Reflow 比其 Repaint 会带来更多的资源消耗,因此,我们应该尽量减少 Reflow 的发生,或者将其转化为只会触发 Repaint 操作的代码。
var tipBox = document.createElement('div');
document.body.appendChild('tipBox');//reflow
var tip1 = document.createElement('div');
var tip2 = document.createElement('div');
tipBox.appendChild(tip1);//reflow
tipBox.appendChild(tip2);//reflow
如上的代码,会产生三次reflow,优化后的代码如下:
var tipBox = document.createElement('div');
tip1 = document.createElement('div');
tip2 = document.createElement('div');
tipBox.appendChild(tip1);
tipBox.appendChild(tip2);
document.body.appendChild('tipBox');//reflow
当然还可以利用 display 来减少reflow次数:
var tipBox = document.getElementById('tipBox');
tipBox.style.display = 'none';//reflow
tipBox.appendChild(tip1);
tipBox.appendChild(tip2);
tipBox.appendChild(tip3);
tipBox.appendChild(tip4);
tipBox.appendChild(tip5);
tipBox.style.width = 120;
tipBox.style.height = 60;
tipBox.style.display = 'block';//reflow