天天看點

關于Repaint(重繪)與Reflow(回流)

關于回流和重繪在剛開始學習前端時一般不會太在意,因為其影響的大多是運作時的性能問題。

顯然,頻繁地進行回流和重繪會導緻運作性能的下降,是以,在要求性能的時候,往往要注意減少頁面的回流和重繪。

概念

repaint重繪

不會改變DOM的排版,僅僅改變某個元素的一些表現。比如,字型顔色的變化,背景顔色,透明度,輸入框的值的改變等等。

reflow回流

這個相較于重繪的改動更大。當DOM的排版改變時,會觸發重繪。是以,改變某個元素的長寬,顯示與否(display),以及浏覽器視窗大小改變,字型大小改變,擷取浏覽器屬性值(offsetHeight、offsetWidth),滾動頁面,DOM操作等。

如何減少

  • 盡可能在DOM末梢通過改變class來修改元素的style屬性:盡可能的減少受影響的DOM元素。
<div class='outer'>
    <div class='inner'>abc</div>
</div>
outer = document.getElementsByClassName('outer');
inner = document.getElementsByClassName('inner');
//bad
outer.style.color = 'red';
//good
inner.style.color = 'red';
           

顯然,兩種方式都改變了“abc”的顔色,但是通過最裡面那層改變導緻的重繪範圍将更小。

  • 避免設定多項内聯樣式:使用常用的class的方式進行設定樣式,以避免設定樣式時通路DOM的低效率。
//bad
inner.style.color = 'red';
inner.style.backgroundColor = 'blue';
...
//good
.newClass {
    color: red;
    background-color: blue;
    ...
}
inner.className += 'newClass';
//jquery
inner.css({'color': 'red', 'background-color': 'blue'});
           

上面第一種方法,分多步對一個元素的樣式進行了修改,這樣每一步都會導緻重繪,性能自然降低。

而第二種和第三種方法,将需要改變的樣式放在一個class中或者一次性改變,隻會發生一次重繪,性能更好。

  • 設定動畫元素position屬性為fixed或者absolute:由于目前元素從DOM流中獨立出來,是以受影響的隻有目前元素,元素repaint。
  • 犧牲平滑度滿足性能:動畫精度太強,會造成更多次的repaint/reflow,犧牲精度,能滿足性能的損耗,擷取性能和平滑度的平衡。
  • 避免使用table進行布局:table的每個元素的大小以及内容的改動,都會導緻整個table進行重新計算,造成大幅度的repaint或者reflow。改用div則可以進行針對性的repaint和避免不必要的reflow。

繼續閱讀