Reflow(回流)和Repaint(重绘) (转)
原文地址:http://blog.csdn.net/qq_18826911/article/details/68924255
首先我们要明白的是,页面的显示过程分为以下几个阶段:
1、生成DOM树(包括display:none的节点)
2、在DOM树的基础上根据节点的集合属性(margin,padding,width,height等)生成render树(不包括display:none,head节点,但是包括visibility:hidden的节点)
3、在render树的基础上继续渲染颜色背景色等样式
Reflow:当render树的一部分或者全部因为大小边距等问题发生改变而需要重建的过程,叫做回流。
reflow会影响到dom的结构渲染,同时会触发repaint,他会改变他本身与所有父辈元素(祖先),这种开销是非常昂贵的,导致性能下降是必然的,页面元素越多效果越明显。
Repaint(重绘):当诸如颜色背景等不会引起页面布局变化,而只需要重新渲染的过程叫做重绘。
repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲染。
通过上述定义,可以很明显看出,重绘的代价要比回流小,毕竟重绘只涉及样式的改变,不涉及到布局。
什么情况下会触发浏览器的repaint/reflow?
1.DOM元素的添加、修改(内容)、删除( Reflow + Repaint)
2.仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)
3.应用新的样式或者修改任何影响元素外观的属性
4.Resize浏览器窗口、滚动页面
5.读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE))
6.改变字体大小
7.添加、删除样式表
8.内容的改变,如用户在输入框中写字
9.激活伪类
10.设置style属性
如何避免repaint/reflow?
1.先将元素从document中删除,完成修改后再把元素放回原来的位置
2.将元素的display设置为”none”,完成修改后再把display修改为原来的值*
3.如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createTextNode(‘keenboy test 111’));
fragment.appendChild(document.createElement(‘br’));
fragment.appendChild(document.createTextNode(‘keenboy test 222’));
document.body.appendChild(fragment);
4.集中修改样式**
(1)尽可能少的修改元素style上的属性
(2)尽量通过修改className来修改样式
(3)通过cssText属性来设置样式值
element.style.width=”80px”; //reflow
element.style.height=”90px”; //reflow
element.style.border=”solid 1px red”; //reflow
以上就产生多次reflow,调用的越多产生就越多
element.style.cssText=”width:80px;height:80px;border:solid 1px red;”; //reflow
(4)缓存Layout属性值
var left=elem.offsetLeft; 多次使用left也就产生一次reflow
(5)设置元素的position为absolute或fixed
元素脱离标准流,也从DOM树结构中脱离出来,在需要reflow时只需要reflow自身与下级元素
(6)避免使用expression,他会每次调用都会重新计算一遍(包括加载页面)
(7)尽量不要用table布局
table元素一旦触发reflow就会导致table里所有的其它元素 reflow。在适合用table的场合,可以设置table-layout为auto或fixed,这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
- 顶
- 踩