回流(reflow): 當(dāng)render樹(渲染樹)中的一部分或者全部因為大小邊距等引起結(jié)構(gòu)變化 而需要重建的過程叫做回流啰扛;
重繪(repaint):當(dāng)render 樹中的一些元素需要更新屬性义锥,而這些屬性只是影響元素的外觀,風(fēng)格姻采,而不會影響布局的,比如background-color私植。則就叫稱為重繪官边。
每個頁面至少需要一次回流,就是在頁面第一次加載的時候锄贼。在回流的時候票灰,瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹宅荤,完成回流后屑迂,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪冯键。
注意:回流一定會引起重繪惹盼, 重繪不一定會引起回流;而且每個頁面都至少需要一次回流惫确,就是頁面第一次開始加載的時候手报。
可能會有人問蚯舱, 什么是render樹?在了解render數(shù)之前 我們先了解一下瀏覽器在頁面加載完成后到頁面顯示的中間過程:
首先將得到的代碼解析生成dom樹掩蛤,這個dom樹里邊包括了所有的HTML的標(biāo)簽 包括display:none 還有js動態(tài)添加的元素等枉昏;
瀏覽器把所有的樣式解析成樣式結(jié)構(gòu)體;
在dom樹和樣式結(jié)構(gòu)體組合后構(gòu)建成render樹 (不包括display:none揍鸟,head節(jié)點兄裂,因為這些節(jié)點不會用于呈現(xiàn),而且不會影響呈現(xiàn) 所以不再render樹中阳藻; 但會包括visibility:hidden的節(jié)點)懦窘;
一旦render tree構(gòu)建完畢后,瀏覽器就可以根據(jù)render 樹來繪制頁面了稚配。
render樹
render樹的節(jié)點叫做渲染器畅涂; 渲染器在文檔解析和dom樹創(chuàng)建之后創(chuàng)建,會計算dom節(jié)點的樣式信息道川;
如果說元素設(shè)置成了display:none或者元素的子孫元素繼承了display:none的屬性午衰,那么元素的render樹則不會被創(chuàng)建, 節(jié)點的子類display屬性決定該節(jié)點創(chuàng)建怎樣的渲染器冒萄。
引起回流和重繪的原因是頁面布局和幾何屬性發(fā)生了改變臊岸。
何時觸發(fā)回流和重繪
repaint重繪:
reflow回流必定引起repaint重繪,重繪可以單獨觸發(fā)
背景色尊流、顏色帅戒、字體改變(注意:字體大小發(fā)生變化時,會觸發(fā)回流)reflow回流:
頁面第一次渲染(初始化)
DOM樹變化(如:增刪節(jié)點)
Render樹變化(如:padding改變)
瀏覽器窗口resize
當(dāng)你查詢布局信息崖技,包括offsetLeft逻住、offsetTop、offsetWidth迎献、offsetHeight瞎访、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height吁恍、調(diào)用了getComputedStyle()或者IE的currentStyle時扒秸,瀏覽器為了返回最新值,會觸發(fā)回流冀瓦。
性能優(yōu)化
- 盡量避免改變布局屬性伴奥。如width, height, left, top。
- 除了transforms 或者 opacity屬性都會引起重繪翼闽,做動畫的時候要注意拾徙, - 盡量使用這兩個屬性;
- 使用Flexbox肄程。
- 避免多次讀取部分布局屬性(同上)
- 將復(fù)雜的節(jié)點元素脫離文檔流锣吼,降低回流成本
-
css
- 減少選擇器的復(fù)雜性选浑。
- 避免逐個修改節(jié)點樣式,盡量一次性修改玄叠,減少style修改所影響元素的數(shù)量,使用cssText來替代要多次修改的style屬性.
-
js
我們也知道回流的花銷也不小古徒,如果每句JS操作都去回流重繪的話,瀏覽器可能就會受不了读恃。所以很多瀏覽器都會優(yōu)化這些操作隧膘,瀏覽器會維護(hù)1個隊列,把所有會引起回流寺惫、重繪的操作放入這個隊列疹吃,等隊列中的操作到了一定的數(shù)量或者到了一定的時間間隔,瀏覽器就會flush隊列西雀,進(jìn)行一個批處理萨驶。這樣就會讓多次的回流、重繪變成一次回流重繪艇肴。