前端性能優化 —— reflow(回流)和repaint(重繪)


簡要:整個在瀏覽器的渲染過程中(頁面初始化,用戶行為改變界面樣式,動畫改變界面樣式等)reflow(回流)和repaint(重繪) 會大大影響web性能,尤其是手機頁面。因此我們在頁面設計的時候要盡量減少reflow和repaint。

什么是reflow和repaint(原文鏈接:http://www.cnblogs.com/Peng2014/p/4687218.html)

reflow:例如某個子元素樣式發生改變,直接影響到了其父元素以及往上追溯很多祖先元素(包括兄弟元素),這個時候瀏覽器要重新去渲染這個子元素相關聯的所有元素的過程稱為回流。

reflow:幾乎是無法避免的。現在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯 示與隱藏)等,都將引起瀏覽器的 reflow。鼠標滑過、點擊……只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲 染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響着。

repaint:如果只是改變某個元素的背景色、文 字顏色、邊框顏色等等不影響它周圍或內部布局的屬性,將只會引起瀏覽器 repaint(重繪)。repaint 的速度明顯快於 reflow

下面情況會導致reflow發生

1:改變窗口大小

2:改變文字大小

3:內容的改變,如用戶在輸入框中敲字

4:激活偽類,如:hover

5:操作class屬性

6:腳本操作DOM

7:計算offsetWidth和offsetHeight

8:設置style屬性

 

那么為了減少回流要注意哪些方式呢?

1:不要通過父級來改變子元素樣式,最好直接改變子元素樣式,改變子元素樣式盡可能不要影響父元素和兄弟元素的大小和尺寸

2:盡量通過class來設計元素樣式,切忌用style

var bstyle = document.body.style; // cache
 
bstyle.padding = "20px" ; // reflow, repaint
bstyle.border = "10px solid red" ; //  再一次的 reflow 和 repaint
 
bstyle.color = "blue" ; // repaint
bstyle.backgroundColor = "#fad" ; // repaint
 
bstyle.fontSize = "2em" ; // reflow, repaint
 
// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode( 'dude!' ));
 
對上面代碼優化:
.b-class{
  padding:20px;
  color:blue;
  border:10px solid red;
  background-color:#fad;
  font-size:2em;
}
$div.addClass("b-class");
 

3:實現元素的動畫,對於經常要進行回流的組件,要抽離出來,它的position屬性應當設為fixed或absolute

4:權衡速度的平滑。比如實現一個動畫,以1個像素為單位移動這樣最平滑,但reflow就會過於頻繁,CPU很快就會被完全占用。如果以3個像素為單位移動就會好很多。

5:不要用tables布局的另一個原因就是tables中某個元素一旦觸發reflow就會導致table里所有的其它元素reflow。在適合用table的場合,可以設置table-layout為auto或fixed,

6:這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍。

7:css里不要有表達式expression

8:減少不必要的 DOM 層級(DOM depth)。改變 DOM 樹中的一級會導致所有層級的改變,上至根部,下至被改變節點的子節點。這導致大量時間耗費在執行 reflow 上面。

9:避免不必要的復雜的 CSS 選擇器,尤其是后代選擇器(descendant selectors),因為為了匹配選擇器將耗費更多的 CPU。

10: 盡量不要過多的頻繁的去增加,修改,刪除元素,因為這可能會頻繁的導致頁面reflow,可以先把該dom節點抽離到內存中進行復雜的操作然后再display到頁面上。

在div.first里面加入div.second,在div.second里面加入div.third:

$divS = $("<div class='second'></div>");

$(div.first).append($divS));//reflow

$divT = $("<div class='third'></div>");

$divS.append($divT);//reflow

優化代碼:

$divS = $("<div class='second'></div>");

$divT = $("<div class='third'></div>");

$divS.append($divT);

$(div.first).append($divS));//reflow

或者:

var $divF = $(div.first);

$divS = $("<div class='second'></div>");

$divS.hide();

$(div.first).append($divS));

$divT = $("<div class='third'></div>");

$divS.append($divT);

$divS.show();//reflow

 

 

11:請求如下值offsetTop, offsetLeft, offsetWidth, offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,瀏覽器會發生reflow,建議將他們合並到一起操作,可以減少回流的次數。

如果我們要經常去獲取和操作這些值,則可以先將這些值緩存起來例如:

var windowHeight = window.innerHeight;//reflow

for(i=0;i<10;i++){

  $body.height(windowHeight++);

  一系列關於windowHeight的操作.......

}

 

參考鏈接:

http://ued.alimama.com/front-end/quick-tips-among-yahoo-n-rules/

http://www.cnblogs.com/Peng2014/p/4687218.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM