本文被收納於: 從零開始的大前端築基之旅(深刻淺出,持續更新~)javascript
迴流與重繪,會影響頁面性能,每次這兩個都會被同時說起,關係就好像KFC邊上必定會有MC同樣親密的讓人摸不到頭腦。css
要理解迴流與重繪,首先要明白瀏覽器請求回來以後發生了什麼html
在頁面加載時,瀏覽器渲染過程以下:前端
爲了構建渲染樹,瀏覽器主要完成了如下工做:java
渲染樹中只會包含可見節點。不可見節點包括:css3
注意,利用visibility和opacity隱藏的節點,仍是會顯示在渲染樹上的。segmentfault
因爲瀏覽器使用流式佈局,對
Render Tree
的計算一般只須要遍歷一次就能夠完成,但table
及其內部元素除外,他們可能須要屢次計算瀏覽器
經過構造渲染樹,將可見DOM節點以及它對應的樣式結合起來,這時候須要計算它們在設備視口(viewport)內的確切位置和大小,這個計算的階段就是迴流。每一個頁面至少須要一次迴流,就是在頁面第一次加載的時候,這時候是必定會發生迴流的,由於要構建render tree。緩存
經過構造渲染樹和迴流階段,咱們肯定了可見節點,以及可見節點的樣式和具體的幾何信息(位置、大小),將渲染樹的每一個節點都轉換爲屏幕上的實際像素,這個階段就叫作重繪節點。wordpress
當Render Tree
中部分或所有元素的尺寸、結構、或某些屬性發生改變時,瀏覽器將從新渲染部分或所有文檔,這時發生的就是迴流。
會致使迴流的操做:
DOM
元素CSS
僞類(例如::hover)
當頁面中元素樣式的改變並不影響它在文檔流中的位置時(例如:color
、background-color
、visibility
等),瀏覽器會將新樣式賦予給元素並從新繪製它,這個過程稱爲重繪。
迴流必定會觸發重繪,而重繪不必定會迴流
迴流比重繪的代價要高,至於具體的資源開銷跟render樹有多少節點須要從新構建有關。有時即便僅僅迴流一個單一的元素,它的父元素以及任何跟隨它的元素也會產生迴流。
大多數瀏覽器都會經過隊列化修改並批量執行來優化重排過程。:
瀏覽器會維護一個隊列,把全部引發迴流和重繪的操做放入隊列中,若是隊列中的任務數量或者時間間隔達到一個閾值的,瀏覽器就會將隊列清空,進行一次批處理,這樣能夠把屢次迴流和重繪變成一次。
可是!當你獲取佈局信息的操做的時候,會強制隊列刷新,好比當你訪問如下屬性或者使用如下方法:
由於隊列中可能會有影響到這些屬性或方法返回值的操做,即便你但願獲取的信息與隊列中操做引起的改變無關,瀏覽器也會強行清空隊列,確保你拿到的值是最精確的。
避免頻繁操做樣式,最好一次性重寫style
屬性,或者將樣式列表定義爲class
並經過更改元素class
屬性來應用樣式。
經過style屬性設置樣式致使迴流。避免設置多級內聯樣式,由於每一個都會形成迴流,樣式應該合併在一個外部類,這樣當該元素的class屬性可被操控時僅會產生一個reflow。
避免頻繁操做DOM
,建立一個documentFragment
,在它上面應用全部DOM操做
,最後再把它添加到文檔中。
DocumentFragment 節點不屬於文檔樹,在把它插入文檔節點以前,隨便給他增刪節點都不會引發迴流
使用cloneNode和replaceChild有相似的效果
先爲元素設置display: none
,操做結束後再把它顯示出來。由於在display
屬性爲none
的元素上進行的DOM
操做不會引起迴流和重繪。
避免頻繁讀取會引起迴流/重繪的屬性,若是確實須要屢次使用,就用一個變量緩存起來。
對具備複雜動畫的元素使用絕對定位,使它脫離文檔流,不然會引發父元素及後續元素頻繁迴流。
避免使用CSS
表達式(例如:calc()
)
避免使用table佈局
table是個和罕見的能夠影響在它們以前已經進入的DOM元素的顯示的元素。即便一些小的變化將致使表格(table)中的全部其餘節點回流。
css3硬件加速(GPU加速)
使用css3硬件加速,可讓transform、opacity、filters這些動畫不會引發迴流重繪
若是你收穫了新知識,或者收穫了左側精美圖片,請點個贊吧~
一個贊頂100閱讀量,告訴我你曾來過、看過,並在這裏不枉此行吧!!
以上內容參考了下面的資料,若有雷同,那很正常。。(這句話真不錯~)
參考文檔: