理解瀏覽器的重繪與回流(repaint&&reflow)


  今天在做練習的時候,遇到了重繪與回流這個詞,表示連個毛都沒有聽過。遂查之,首先將網上的(http://blog.sina.com.cn/s/blog_8dace7290102wezv.html)關於這兩個詞的領悟粘貼如下:

一.  瀏覽器渲染過程  

渲染:就是把瀏覽器把HTML代碼以css定義的規則顯示在瀏覽器窗口的過程 

瀏覽器解析HTML的基本過程:
 
1  用戶輸入網址,瀏覽器向服務器發出請求,服務器返回html文件
 
2  瀏覽器載入html代碼,發現標簽內有一個標簽引用外部css文件
 
3 瀏覽器又發出css文件的請求,服務器返回這個css文件
 
4 瀏覽器繼續載入html中的部分的代碼,並且css文件已經拿到手了,可以渲染頁面
 
5 瀏覽器在代碼中發現一個 重繪與回流標簽引用關了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染后面的代碼
 
6 服務器返回圖片文件,由於圖片占用了一定面積,影響了后面段落的排布,因此瀏覽器需要回過頭來渲染這部分代碼
 
7  瀏覽器發現了一個包含一行javascript代碼的script標簽,趕快運行它
 
8 javascript腳本執行了這條語句,命令瀏覽器隱藏代碼中某個,杯具了,突然就少了一個元素,瀏覽器不得不重新渲染這部分代碼
 
9  終於等到的到來,瀏覽器淚流滿面 
 
10   等等,還沒完,用戶點了一個界面中的“換膚”按鈕,javascript讓瀏覽器換了一個標簽中的css的路徑
 
 
11 瀏覽器召集了在座的各位:"大伙需要收拾下行李,咱得重新來過",瀏覽器向服務器請求了新的css文件,重新渲染頁面當頁面的布局發生變化時,瀏覽器會回過頭來重新渲染,這就是頁面變慢的原因。
 
二.  渲染樹(render tree)

1.瀏覽器把獲取到的HTML代碼解析成一棵DOM樹,HTML中的每個標簽(tag)都是DOM樹中的一個節點,根節點就是我們常用的document對象。DOM樹里包含了HTML所有標簽,包括display:none隱藏,還有用JS動態添加的元素等;

2.瀏覽器把所有樣式(用戶定義的css和用戶代理)解析成樣式結構體,在解析過程中會去掉瀏覽器不能識別的樣式,比如IE會去掉-moz開頭的樣式,而Firefox會去掉_開頭的樣式;

3.DOM樹和樣式結構體組合后構建render tree(渲染樹),render tree類似於DOM樹,但區別很大,render tree 能識別樣式,render tree的每一個節點都有自己的樣式,而且render tree中不包含隱藏的節點(比如display:none的節點,還有head節點),因為這些節點不會用於呈現,而且不會影響呈現。

注意:visibility:hidden隱藏的元素還是會包含到render tree中,因為visibility:hidden會影響布局(layout),會占有空間。根據css2的標准,render tree中的每個節點都稱為Box(Box demensions),理解頁面元素為一個具有填充,邊距,邊框和位置的盒子。

4.一旦render tree構建完成后,瀏覽器就可以根據render tree來繪制頁面了。

 

注意:回流必將引起重繪,而重繪不一定會引起回流。

 

三.  重繪與回流的定義

  重繪:當前元素的樣式(背景顏色、字體顏色等)發生改變的時候,我們只需要把改變的元素重新的渲染一下即可,重繪對瀏覽器的性能影響較小,所以 一般不考慮。

  發生重繪的情形:改變容器的外觀風格等,比如background:black等。改變外觀,不改變布局,不影響其他的dom。

 

  回流:是指瀏覽器為了重新渲染部分或者全部的文檔而重新計算文檔中元素的位置和幾何構造的過程。

  因為回流可能導致整個dom樹的重新構造,所以是性能的一大殺手

  一個元素的回流導致了其所有子元素以及DOM中緊隨其后的祖先元素的隨后的回流.

 

四.  觸發回流的操作

1.調整窗口大小(Resizing the window)

2.改變字體(Changing the font)

3.增加或者移除樣式表(Adding or removing a stylesheet)

4.內容變化,比如用戶在input框中輸入文字(Content changes, such as a user typing text in an input box)

5.激活 CSS 偽類,比如 :hover (IE 中為兄弟結點偽類的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling)

6.操作 class 屬性(Manipulating the class attribute)

7.腳本操作 DOM(A script manipulating the DOM)

8.計算 offsetWidth 和 offsetHeight 屬性(Calculating offsetWidth and offsetHeight)

9.設置 style 屬性的值 (Setting a property of the style attribute)

10.fixed定位的元素,在拖動滾動條的時候會一直回流

 

五.  如何避免回流

  1.  一起變化

  如果要改變一個元素的樣式,可以將所有樣式集中在一個class上面一次變化,而不是變化幾次,比如:

<style type="text/css">
     .changeStyle { width: 100px; height: 100px; }
 </style>
 <script type="text/javascript">
     $(document).ready(function () {
         var el = $('id');
         //1
         el.css('width', '100px');
         el.css('height', '100px');
         //2
         el.css({ 'width': '100px;', 'height': '100px;' });
         //3 
         el.addClass('changeStyle');
     });
 </script>

  應該使用第三種,這樣只重繪一次。

  2.  具有動畫效果請使用absolute

  3.  避免使用表格布局

  4.  不要使用CSS表達式

  5.  在最末改變元素

  因為回流是自上而下的,所以下不及上,我們在最后面修改信息對全局影響越少。

  6.  動畫移動時候,要控制

  比如我們拖動元素時候,我是在他x或者y坐標改變5px才操作,這樣雖說降低了平滑度,但是對性能有提高

  7.  如果你想讓復雜的表現發生改變,例如動畫效果,那么請在這個流動線之外實現它。使用position-absolute或position-fixed來實現它。

  8.  既然計算offsetWidth也會引起回流,那么就拿一個變量保存它

  9.  當我們需要向文檔中添加節點時,可以用文檔碎片的方式去解決這個問題的,當我們需要給DOM中添加新的元素的時候,先將其放在一個容器中,然后統一添加,這樣就只產生了一次回流。如下:

var frg = document.createDocumentFragment();//創建了一個文檔碎片:相當於一個容器,把動態創建的li先放到容器中,最后一起添加到頁面中(只引發一次回流)
 for (var i = 0; i < 10; i++) {
     var oLi = document.createElement("li");
     oLi.onmouseover = function () {
         this.style.backgroundColor = "#22b909";
     }
     oLi.onmouseout = function () {
         this.style.backgroundColor = "";
     }
     frg.appendChild(oLi);
  }
 oUl.appendChild(frg);

資料來源:

  http://aijuans.iteye.com/blog/1910614

  http://m.blog.csdn.net/article/details?id=50696328

  http://www.360doc.cn/article/10504424_435836011.html

  http://www.zhangxinxu.com/wordpress/2010/01/%E5%9B%9E%E6%B5%81%E4%B8%8E%E9%87%8D%E7%BB%98%EF%BC%9Acss%E6%80%A7%E8%83%BD%E8%AE%A9javascript%E5%8F%98%E6%85%A2%EF%BC%9F/

    

 

回流是指瀏覽器為了重新渲染部分或者全部的文檔而重新計算文檔中元素的位置和幾何構造的過程


免責聲明!

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



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