回流 reflow 和重繪 repaint

2021-10-05 02:38:20 字數 3600 閱讀 1141

首先我們要明確頁面在文件載入完成之後到完全顯示中間的過程是1.根據文件生成dom樹(包括display:none的節點)2.在dom樹基礎上根據節點的幾何屬性(margin/padding/width/height等)生成render樹(不包括display:none、head節點但會包含visibility:hidden節點)3.在render樹基礎上進行進一步渲染包括color,outline等樣式

r ef

low:

當ren

der樹

中的一部

分或者全

部因為大

小邊距等

問題發生

改變而需

要重建的

過程叫做

回流

\color

reflow

:當re

nder

樹中的一

部分或者

全部因為

大小邊距

等問題發

生改變而

需要重建

的過程叫

做回流rep

aint

:當元素

的一部分

屬性發生

變化,如

外觀背景

色不會引

起布局變

化而需要

重新渲染

的過程叫

做重

繪\color

repain

t:當元

素的一部

分屬性發

生變化,

如外觀背

景色不會

引起布局

變化而需

要重新渲

染的過程

叫做重繪

這個問題其實很簡單,什麼引起的,看定義不就可以了?

問題是引起的原因可能會很多

籠統來說當頁面的布局和幾何屬性發生變化的時候就會引起回流。具體來說大概分別5大類:

1.首當其衝自然是dom樹結構變化,比如你刪除或者新增某個node.

2.元素幾何屬性變化,包括margin,padding,height,width,border等

3.頁面渲染初始化

4.獲取某些屬性。雖然瀏覽器引擎可能會針對重排做了優化,比如opera,它會等到有足夠 數量的變化發生,或者等到一定的時間,或者等乙個執行緒結束,再一起處理,這樣就只發生一次重排。但除了render樹的直接變化,當獲取一些屬性時,瀏覽器為取得 正確的值也會觸發回流。這樣就使得瀏覽器的優化失效了。這些屬性包括:offsettop、offsetleft、 offsetwidth、offsetheight、scrolltop、scrollleft、scrollwidth、scrollheight、 clienttop、clientleft、clientwidth、clientheight、getcomputedstyle() (currentstyle in ie)。所以,在多次使用這些值時應進行快取。(這段是直接引用的。)

5.瀏覽器視窗發生變化-resize事件發生時

以上,其實理解起來很容易。所謂的render樹就是識別了幾何屬性的dom數,好像我們畫人體的時候,dom樹是先確定都有什麼比如四肢,頭部,身體,其他器官等;而render樹則是確定這個人的高矮胖瘦,頭髮是否蓋眼睛等,如果我們在繪畫過程中發現脖子長了那就慘了,脖子下面都要重畫。這就是回流了。如果發現只是手指畫的有問題也還是要回流但我們只需要重畫手指。(當然,我說的是手就是手,沒什麼特別造型的時候);當我們的render樹完事了,也就是人體大概輪廓我們都畫好了,就可以上色了,換個髮色這種我們叫重繪。

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.

(document.

createtextnode

('abc!'))

;

現在我們大概都能得出的結論是:回流比重繪的代價要高,至於具體的花銷跟render樹有多少節點需要重新構建有關。

還有就是,回流一定會伴隨著重繪,但是重繪不一定會引起回流。

從上面的例項**中可以看到一共七行**引起了6次左右的回流、重繪(上面的**我大老遠從別的頁面拿過來當然不只是就用那一次,哈哈),而且我們剛剛還知道了回流花銷真是不小,那麼瀏覽器是不是真的每次js語句引起了回流他就執行一下呢?恩,後面的內容我是看的參考資料的:等佇列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush佇列,進行乙個批處理。這樣就會讓多次的回流、重繪變成一次回流重繪。

但是儘管瀏覽器挺機智地幫我們優化了**,我們自己作死也是沒救的,比如你去請求

offsettop, offsetleft, offsetwidth, offsetheight

scrolltop/left/width/height

clienttop/left/width/height

width,height

請求了getcomputedstyle(), 或者 ie的 currentstyle

瀏覽器為了給你返回乙個比較精確的答案,他會提前flush佇列,因為佇列中可能會有影響這些值的操作。

所以我們可以做的是:

1.將那些改變樣式的操作集合在一次完事,直接改變classname或者csstext

2.讓要操作的元素進行離線處理,處理完事以後再一起更新

(1)使用documentfragment進行快取操作,引發一次回流和重繪

課外延伸:

documentfragment 節點不屬於文件樹,繼承的 parentnode 屬性總是 null。

不過它有一種特殊的行為,該行為使得它非常有用,即當請求把乙個 documentfragment 節點插入文件樹時,插入的不是 documentfragment 自身,而是它的所有子孫節點。這使得 documentfragment 成了有用的佔位符,暫時存放那些一次插入文件的節點。它還有利於實現文件的剪下、複製和貼上操作。

其實他就是乙個游離在dom樹外面的容器,所以你在把它插入文件節點之前,隨便給他增刪節點都不會引起回流

(2)使用display:none,只引發兩次回流和重繪。道理跟上面的一樣。因為display:none的元素不會出現在render樹

(3)使用clonenode和replacechild技術,引發一次回流和重繪(這條沒太明白)

3.不要經常訪問會引起瀏覽器flush佇列的屬性,非要高頻訪問的話建議快取到變數;

4.將需要多次重排的元素,position屬性設為absolute或fixed,這樣此元素就脫離了文件流,它的變化不會影響到其他元素。例如有動畫效果的元素就最好設定為絕對定位;

5.盡量不要使用**布局,如果沒有定寬**一列的寬度由最寬的一列決定,那麼很可能在最後一行的寬度超出之前的列寬,引起整體回流造成table可能需要多次計算才能確定好其在渲染樹中節點的屬性,通常要花3倍於同等元素的時間。

Reflow 回流 和Repaint 重繪

首先我們要明白的是,頁面的顯示過程分為以下幾個階段 1 生成dom樹 包括display none的節點 2 在dom樹的基礎上根據節點的集合屬性 margin,padding,width,height等 生成render樹 不包括display none,head節點,但是包括visibility...

回流 reflow 和重繪 repaint

首先先介紹瀏覽器解析的工作原理 1.解析html文件建立dom樹 2.解析css 包含外部css以及js生成的 構建渲染樹,計算出節點的樣式 3.布局渲染樹,以根節點遞迴呼叫,計算每乙個節點的大小,位置等,給出每乙個節點出現在螢幕的精準目標 4.繪製渲染樹,遍歷渲染樹,每個幾點使用ui後端層來繪製 ...

reflow 回流 和repaint 重繪

dom節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱為reflow 當盒模型的位置,大小以及其他屬性,如顏色,字型,等確定下來之後,瀏覽器便開始繪製內容,這個過程稱為repaint。頁面在首次載入時必然會經歷reflow和repaint。reflow和rep...