HTML頁面的重繪(repaint)和重流(reflow)


  重流(Reflow)是指布局引擎為frame計算圖形的過程。 frame是一個矩形,擁有寬高和相對父容器的偏移。frame用來顯示盒模型(content model), 但一個content model可能會顯示為多個frame,比如換行的文本每行都會顯示為一個frame。

  重繪(Repaint)發生在元素的可見性發生變化時,比如背景色、前景色等。 因此回流必然會引起重繪

  

重流的原因

  • 初始化(Initial)。DOM載入后的第一次回流,將會遍歷所有frame。
  • 漸進(Incremental)。當一個frame發生漸進回流時,意味着它前面的元素都沒有變, 而是它里面的元素變了。這會引起自底向上的作用。
  • 改變大小(Resize)。元素的容器邊界發生變化時,此時元素內部狀態沒變。 在計算自頂向下的布局約束的同時,可以復用內部狀態。
  • 樣式改變(StyleChange)。整個frame樹都應得到遍歷。
  • Dirty。當一個容器已經緩存了多個子元素的Incremental回流時,該容器出於Dirty的狀態。

 

如果你是Web開發者,可能更關注的是哪些具體原因會引起瀏覽器的回流,下面羅列一下:

  1. 調整窗口大小
  2. 改變字體大小
  3. 樣式表變動
  4. 元素內容變化,尤其是輸入控件
  5. CSS偽類激活
  6. DOM操作
  7. offsetWidth, width, clientWidth, scrollTop/scrollHeight的計算, 會使瀏覽器將漸進回流隊列Flush,立即執行回流。

 

 

最佳實踐

對我們Web開發者最有用的還是如何去做,才能減少頁面回流。先來個例子:

 

var s = document.body.style; 

s.padding = "2px"; // 回流+重繪
s.border = "1px solid red"; // 再一次 回流+重繪

s.color = "blue"; // 再一次重繪
s.backgroundColor = "#ccc"; // 再一次 重繪

s.fontSize = "14px"; // 再一次 回流+重繪

// 添加node,再一次 回流+重繪
document.body.appendChild(document.createTextNode('abc!'));

 

可以看到每次DOM元素的樣式操作都會引發重繪,如果涉及布局還會引發回流。

避免大量頁面回流的手段也有很多,其本質都是盡量減少引起回流和重繪的DOM操作:

  1. 避免逐項更改樣式。最好一次性更改style屬性,或者將樣式列表定義為class並一次性更改class屬性。
  2. 避免循環操作DOM。創建一個documentFragment或div,在它上面應用所有DOM操作,最后再把它添加到window.document。
  3. 避免循環讀取offsetLeft等屬性。在循環之前把它們存起來。
  4. 絕對定位具有復雜動畫的元素。絕對定位使它脫離文檔劉,否則會引起父元素及后續元素大量的回流。

 


免責聲明!

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



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