迴流(reflows)和重繪(repaints)

前言

前段時間,用vue作了一個吸頂等功能,實現這個功能會涉及到監聽頁面滾動,天然而言就會涉及到讀取相關屬性,頻繁的讀取屬性,會致使reflow,也就會影響頁面的性能,爲了後面開發過程當中,儘可能寫出更優的代碼,所以總結一下回流和重繪的相關知識點css

瀏覽器的渲染過程

要了解迴流和重繪,首先要知道瀏覽器客戶端的渲染過程,主要分爲如下步驟:vue

  1. 解析HTML生成DOM樹
  2. 解析CSS生成CSSDOM規則樹
  3. 將CSSDOM規則樹和DOM樹合併成一個Render Tree
  4. 根據Render Tree來佈局,計算每一個節點的大小位置信息
  5. 將Render Tree每一個節點繪製到屏幕

什麼是迴流(reflows)

迴流(reflows)是指網絡瀏覽器爲了從新渲染部分文檔或者所有文檔而從新計算文檔中元素的位置和幾何結構的過程,簡單來講,就是頁面上某些元素的大小、位置或者顯示隱藏等發生改變致使頁面從新構建的過程瀏覽器

什麼是重繪(repaints)

當頁面中元素樣式的改變並不影響它在文檔流中的位置時(例如:color、background-color、visibility等),瀏覽器會將新樣式賦予給元素並從新繪製它,這個過程稱爲重繪。緩存

特色:迴流必將引發重繪,重繪不必定引發迴流 迴流比重繪的代價更高網絡

什麼會致使迴流(reflows)、重繪(repaints)?

如下狀況會致使迴流:佈局

  1. 調整瀏覽器窗口大小
  2. 元素字體大小變化
  3. 腳本操做(添加或者刪除)DOM(可見的,對display:none的元素進行操做不會引發迴流、重繪)
  4. 元素的位置或者大小變化
  5. 內容改變引起的尺寸變化,如文本改變(用戶在input框中輸入文字)或者圖片大小改變而引發的寬度和高度改變
  6. 激活CSS僞類(例如:hover)
  7. 計算 offsetWidth 和 offsetHeight 屬性等

一些經常使用且會致使迴流的屬性和方法:性能

  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • scrollIntoView()、scrollIntoViewIfNeeded()、scrollTo
  • getComputedStyle()、getBoundingClientRect()

如何避免迴流、重繪?

1. css

  • 避免使用table佈局
    在佈局完成以前,table常常須要多個關口,由於table能夠影響在它以前進入DOM的元素的顯示。例如,因爲表格的最後的一行內容過長而致使縱列大小的徹底改變。另外還有一點就是,即便一些小的變化將致使表格(table)中的全部其餘節點回流。
  • 犧牲平滑度換取速度
    意思是指您可能想每次1像素移動一個動畫,可是若是此動畫及隨後的迴流使用了100%的CPU,動畫就會看上去是跳動的,由於瀏覽器正在與更新迴流作鬥爭。動畫元素每次移動3像素可能在很是快的機器上看起來平滑度低了,但它不會致使CPU在較慢的機器和移動設備中抖動。
  • 將動畫效果應用到position屬性爲absolute或fixed的元素上
    他們不會影響其餘元素的佈局,不會致使迴流,性能消耗更低
  • 避免使用CSS的JavaScript表達式 (僅 IE 瀏覽器),如calc()
  • 避免設置多項內聯樣式
    經過style屬性設置會致使迴流,避免設置多項內聯樣式(不要一個一個改變元素的樣式屬性),由於每次都會形成迴流,樣式應該合併在一個外部類(class),直接操做改class,只會產生一次迴流
  • 儘量在DOM樹的最末端改變class
    迴流能夠自上而下,或自下而上的迴流的信息傳遞給周圍的節點。迴流是不可避免的,但能夠減小其影響。儘量在DOM樹的裏面改變class,能夠限制了迴流的範圍,使其影響儘量少的節點。例如,應該避免經過改變父類去影響子節點的顯示。

2. js

  • 避免頻繁操做DOM,改善DOM操做致使的迴流
    (1)讓要操做的元素進行離線處理(即讓元素不存在與Render Tree中),處理完後一塊兒更新
    • 使用documentFragment進行緩存操做,引起一次迴流和重繪(主要用於添加元素,先把全部須要添加的元素添加到一個容器 內,而後再添加到body中)
    • 使用display:none 技術(先display:none隱藏元素,而後對元素進行操做,而後顯示元素)
    • 使用cloneNode(true or false) 和 replaceChild 技術

(2)不要常常訪問會引發瀏覽器flush隊列的屬性,若是你確實要訪問,利用緩存
(3)不要一個一個改變元素的樣式屬性,直接改變className,若是動態改變樣式,則使用cssText
(4)讓元素脫離動畫流(應用到position屬性爲absolute或fixed的元素),減小回流的Render Tree的規模字體

相關文章
相關標籤/搜索