首先咱们要明白的是,页面的显示过程分为如下几个阶段:css
一、生成DOM树(包括display:none的节点)express
二、在DOM树的基础上根据节点的集合属性(margin,padding,width,height等)生成render树(不包括display:none,head节点,可是包括visibility:hidden的节点)浏览器
三、在render树的基础上继续渲染颜色背景色等样式缓存
Reflow:当render树的一部分或者所有由于大小边距等问题发生改变而须要重建的过程,叫作回流。markdown
reflow会影响到dom的结构渲染,同时会触发repaint,他会改变他自己与全部父辈元素(祖先),这种开销是很是昂贵的,致使性能降低是必然的,页面元素越多效果越明显。app
Repaint(重绘):当诸如颜色背景等不会引发页面布局变化,而只须要从新渲染的过程叫作重绘。dom
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的影响范围