当前位置:首页 > 浏览器 > 正文

javascript性能优化-repaint和reflow

repaint(重绘) ,repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲染。

reflow(渲染),与repaint区别就是他会影响到dom的结构渲染,同时他会触发repaint,他会改变他本身与所有父辈元素(祖先),这种开销是非常昂贵的,导致性能下降是必然的,页面元素越多效果越明显。

何时发生:

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))

如何避免:

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. 集中修改样式
  4.1尽可能少的修改元素style上的属性
  4.2尽量通过修改className来修改样式
  4.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.4缓存Layout属性值
    var left=elem.offsetLeft; 多次使用left也就产生一次reflow
  4.5设置元素的position为absolute或fixed
    元素脱离标准流,也从DOM树结构中脱离出来,在需要reflow时只需要reflow自身与下级元素
  4.6尽量不要用table布局
    table元素一旦触发reflow就会导致table里所有的其它元素 reflow。在适合用table的场合,可以设置table-layout为auto或fixed,这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
  4.7避免使用expression,他会每次调用都会重新计算一遍(包括加载页面)

严重性:

在性能优先的前提下,性能消耗 reflow大于repaint。

体现:

repaint是某个DOM元素进行重绘;reflow是整个页面进行重排,也就是页面所有DOM元素渲染。

如何触发:

style变动造成repaint和reflow。

不涉及任何DOM元素的排版问题的变动为repaint,例如元素的color/text-align/text-decoration等等属性的变动。

除上面所提到的DOM元素style的修改基本为reflow。例如元素的任何涉及长、宽、行高、边框、display等style的修改。

常见触发场景:
1.触发repaint:1.color的修改,如color=#ddd;
2.text-align的修改,如text-align=center;
3.a:hover也会造成重绘。
4.:hover引起的颜色等不导致页面回流的style变动。
5.等等太多,一时间写出来也太难想了。

2.触发reflow:1.width/height/border/margin/padding的修改,如width=778px;
2.动画,:hover等伪类引起的元素表现改动,display=none等造成页面回流;
3.appendChild等DOM元素操作;
4.font类style的修改;
5.background的修改,注意着字面上可能以为是重绘,但是浏览器确实回流了,经过浏览器厂家的优化,部分background的修改只触发repaint,当然IE不用考虑;
6.scroll页面,这个不可避免;
7.resize页面,桌面版本的进行浏览器大小的缩放,移动端的话,还没玩过能拖动程序,resize程序窗口大小的多窗口操作系统。
8.读取元素的属性(这个无法理解,但是技术达人是这么说的,那就把它当做定理吧):读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE));

如何避免:

说避免那是不可能的,不然就是以前古老的静态页面了,没有交互,那在现在看来,就是一个失败的作品。所以,在我们进行网页设计的时候,就必须尽量减少页面的repaint和reflow。repaint和reflow的目的是为了展示一个新的页面,那么我们在进行页面交互时,尽量通过各种方法减少repaint和reflow但又能展示一个新的页面的目的。所以下面将结合其他技术达人的建议,通过自己的理解,给大家讲解如何避免和优化repaint和reflow:

下面是大神Nicole Sullivan的原话:

1.Change classes on the element you wish to style (as low in the dom tree as possible)
2.Avoid setting multiple inline styles
3.Apply animations to elements that are position fixed or absolute
4.Trade smoothness for speed
5.Avoid tables for layout
6.Avoid JavaScript expressions in the CSS (IE only)
1.尽可能在DOM末梢通过改变class来修改元素的style属性:尽可能的减少受影响的DOM元素。
2.避免设置多项内联样式:使用常用的class的方式进行设置样式,以避免设置样式时访问DOM的低效率。
3.设置动画元素position属性为fixed或者absolute:由于当前元素从DOM流中独立出来,因此受影响的只有当前元素,元素repaint。
4.牺牲平滑度满足性能:动画精度太强,会造成更多次的repaint/reflow,牺牲精度,能满足性能的损耗,获取性能和平滑度的平衡。
5.避免使用table进行布局:table的每个元素的大小以及内容的改动,都会导致整个table进行重新计算,造成大幅度的repaint或者reflow。改用div则可以进行针对性的repaint和避免不必要的reflow。
6.避免在CSS中使用运算式:学习CSS的时候就知道,这个应该避免,不应该加深到这一层再去了解,因为这个的后果确实非常严重,一旦存在动画性的repaint/reflow,那么每一帧动画都会进行计算,性能消耗不容小觑。

暂无评论

发表评论

您必须 [ 登录 ] 才能发表留言!