重绘(repaint)与重排(reflow)
之前初窥浏览器时讲过浏览器对页面的解译呈现其实是一个在解译渲染的同时反复通过重排重绘来自我修整的过程。
重绘其实就是对元素外貌的显现过程,例如颜色,背景图等不会影响布局的属性。
重排也就是根据DOM树与CSS规则树中的相关数据的计算结果确定宽高与位置后进行布局。
通过CSS与JS设置元素例如颜色,背景图等不会影响布局的属性,但会引起重绘,此时不影响布局,只是局部元素的重新渲染,对性能影响不大。
当改变了布局或者改变元素宽高,display等属性时,会引起重排,此时可能会改变DOM树的局部结构,甚至改变整个DOM树,因此浏览器(内部程序)会执行大量的重排工作,很耗性能。
重排会因DOM树中元素的定位(排版)或结构被改变而触发,具体有:
通过JS增加,删除,修改DOM节点;
改变元素的display属性;
改变窗口大小,滚动屏幕;
移动DOM元素;
修改默认字体,大小,行高;
获取offsetTop,scrollTop,clientTop等距离值;
获取元素样式;
......
优化:
1.display:none;的元素不加入DOM树,因此对于需要一次性改动大量DOM元素时,可以先将要增加,删除,修改元素的父级display设为none,在DOM树外执行增加,删除,修改操作后再一次性加回DOM树(display:none;),此过程只进行2次重排;
2.减少改变样式的次数,即将对同一元素的样式设置尽量合并,减少操作;
3.将要进行多次重排的元素属性设为absolute或fixed,这样该元素便脱离了普通流,所以改变定位时不影响DOM结构;
4.缓存经常使用的与重排相关的属性值;例如:for(i = 0; i<aLi.length; i++){}
可改写为:
l = aLi.length;
for(i = l-1 ; i>=0 ; i--){} //这时就不用每进行一次循环就reflow一次去计算aLi.length了
......