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

簡要:整個在瀏覽器的渲染過程當中(頁面初始化,用戶行爲改變界面樣式,動畫改變界面樣式等)reflow(迴流)和repaint(重繪) 會大大影響web性能,尤爲是手機頁面。所以咱們在頁面設計的時候要儘可能減小reflow和repaint。css

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

reflow:例如某個子元素樣式發生改變,直接影響到了其父元素以及往上追溯不少祖先元素(包括兄弟元素),這個時候瀏覽器要從新去渲染這個子元素相關聯的全部元素的過程稱爲迴流。web

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

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

下面狀況會致使reflow發生緩存

1:改變窗口大小app

2:改變文字大小dom

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

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

相關文章
相關標籤/搜索