回流與重繪

瀏覽器的渲染過程

image.png

從上面這個圖上负间,我們可以看到,瀏覽器渲染過程如下:

解析HTML颖杏,生成DOM樹纯陨,解析CSS,生成CSSOM樹
將DOM樹和CSSOM樹結合留储,生成渲染樹(Render Tree)
Layout(回流):根據生成的渲染樹翼抠,進行回流(Layout),得到節(jié)點的幾何信息(位置获讳,大幸跤薄)
Painting(重繪):根據渲染樹以及回流得到的幾何信息,得到節(jié)點的絕對像素
Display:將像素發(fā)送給GPU丐膝,展示在頁面上量愧。


image.png

為了構建渲染樹,瀏覽器主要完成了以下工作:
1.從DOM樹的根節(jié)點開始遍歷每個可見節(jié)點帅矗。
2.對于每個可見的節(jié)點偎肃,找到CSSOM樹中對應的規(guī)則,并應用它們浑此。
3.根據每個可見節(jié)點以及其對應的樣式累颂,組合生成渲染樹。
第一步中凛俱,既然說到了要遍歷可見的節(jié)點紊馏,那么我們得先知道,什么節(jié)點是不可見的蒲犬。不可見的節(jié)點包括

一些不會渲染輸出的節(jié)點朱监,比如script、meta暖哨、link等赌朋。
一些通過css進行隱藏的節(jié)點凰狞。比如display:none篇裁。注意沛慢,利用visibility和opacity隱藏的節(jié)點,還是會顯示在渲染樹上的达布。只有display:none的節(jié)點才不會顯示在渲染樹上团甲。

注意:渲染樹只包含可見的節(jié)點

回流

前面我們通過構造渲染樹,我們將可見DOM節(jié)點以及它對應的樣式結合起來黍聂,可是我們還需要計算它們在設備視口(viewport)內的確切位置和大小躺苦,這個計算的階段就是回流。

為了弄清每個對象在網站上的確切大小和位置产还,瀏覽器從渲染樹的根節(jié)點開始遍歷匹厘,我們可以以下面這個實例來表示:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Critial Path: Hello world!</title>
  </head>
  <body>
    <div style="width: 50%">
      <div style="width: 50%">Hello world!</div>
    </div>
  </body>
</html>

我們可以看到,第一個div將節(jié)點的顯示尺寸設置為視口寬度的50%脐区,第二個div將其尺寸設置為父節(jié)點的50%愈诚。而在回流這個階段,我們就需要根據視口具體的寬度牛隅,將其轉為實際的像素值炕柔。(如下圖)


image.png

重繪

最終,我們通過構造渲染樹和回流階段媒佣,我們知道了哪些節(jié)點是可見的匕累,以及可見節(jié)點的樣式和具體的幾何信息(位置、大小)默伍,那么我們就可以將渲染樹的每個節(jié)點都轉換為屏幕上的實際像素欢嘿,這個階段就叫做重繪節(jié)點。

何時發(fā)生回流重繪

1.添加或刪除可見的DOM元素
2.元素的位置發(fā)生變化
2.元素的尺寸發(fā)生變化(包括外邊距也糊、內邊框炼蹦、邊框大小、高度和寬度等)
4.內容發(fā)生變化显设,比如文本變化或圖片被另一個不同尺寸的圖片所替代框弛。
5.頁面一開始渲染的時候(這肯定避免不了)
6.瀏覽器的窗口尺寸變化(因為回流是根據視口的大小來計算元素的位置和大小的)

注意:回流一定會觸發(fā)重繪,而重繪不一定會回流

瀏覽器的優(yōu)化機制

現代的瀏覽器都是很聰明的捕捂,由于每次重排都會造成額外的計算消耗瑟枫,因此大多數瀏覽器都會通過隊列化修改并批量執(zhí)行來優(yōu)化重排過程。瀏覽器會將修改操作放入到隊列里指攒,直到過了一段時間或者操作達到了一個閾值慷妙,才清空隊列。但是允悦!當你獲取布局信息的操作的時候膝擂,會強制隊列刷新,比如當你訪問以下屬性或者使用以下方法:

offsetTop、offsetLeft架馋、offsetWidth狞山、offsetHeight
scrollTop、scrollLeft叉寂、scrollWidth萍启、scrollHeight
clientTop、clientLeft屏鳍、clientWidth勘纯、clientHeight
getComputedStyle()
getBoundingClientRect

以上屬性和方法都需要返回最新的布局信息,因此瀏覽器不得不清空隊列钓瞭,觸發(fā)回流重繪來返回正確的值驳遵。因此,我們在修改樣式的時候山涡,最好避免使用上面列出的屬性堤结,他們都會刷新渲染隊列。如果要使用它們佳鳖,最好將值緩存起來霍殴。

減少回流和重繪

最小化重繪和重排

由于重繪和重排可能代價比較昂貴,因此最好就是可以減少它的發(fā)生次數系吩。為了減少發(fā)生次數来庭,我們可以合并多次對DOM和樣式的修改,然后一次處理掉穿挨。

const el = document.getElementById('test');
el.style.padding = '5px';
el.style.borderLeft = '1px';
el.style.borderRight = '2px';

例子中月弛,有三個樣式屬性被修改了,每一個都會影響元素的幾何結構科盛,引起回流帽衙。當然,大部分現代瀏覽器都對其做了優(yōu)化贞绵,因此厉萝,只會觸發(fā)一次重排。但是如果在舊版的瀏覽器或者在上面代碼執(zhí)行的時候榨崩,有其他代碼訪問了布局信息(上文中的會觸發(fā)回流的布局信息)谴垫,那么就會導致三次重排。

因此母蛛,我們可以合并所有的改變然后依次處理翩剪,比如我們可以采取以下的方式
使用cssText

const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';

修改CSS的class

const el = document.getElementById('test');
el.className += ' active';

批量修改DOM

當我們需要對DOM對一系列修改的時候,可以通過以下步驟減少回流重繪次數:
1.使元素脫離文檔流
2.對其進行多次修改
3.將元素帶回到文檔中彩郊。
該過程的第一步和第三步可能會引起回流前弯,但是經過第一步之后蚪缀,對DOM的所有修改都不會引起回流,因為它已經不在渲染樹了恕出。
有三種方式可以讓DOM脫離文檔流:
1.隱藏元素询枚,應用修改,重新顯示
2.使用文檔片段(document fragment)在當前DOM之外構建一個子樹剃根,再把它拷貝回文檔哩盲。
3.將原始元素拷貝到一個脫離文檔的節(jié)點中前方,修改節(jié)點后狈醉,再替換原始的元素。

對于復雜動畫效果,使用絕對定位讓其脫離文檔流

對于復雜動畫效果惠险,由于會經常的引起回流重繪苗傅,因此,我們可以使用絕對定位班巩,讓它脫離文檔流渣慕。否則會引起父元素以及后續(xù)元素頻繁的回流。

css3硬件加速(GPU加速)

比起考慮如何減少回流重繪抱慌,我們更期望的是逊桦,根本不要回流重繪。這個時候抑进,css3硬件加速就閃亮登場啦G烤!

劃重點:使用css3硬件加速寺渗,可以讓transform匿情、opacity、filters這些動畫不會引起回流重繪 信殊。但是對于動畫的其它屬性炬称,比如background-color這些,還是會引起回流重繪的涡拘,不過它還是可以提升這些動畫的性能玲躯。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鳄乏,隨后出現的幾起案子跷车,更是在濱河造成了極大的恐慌,老刑警劉巖汞窗,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姓赤,死亡現場離奇詭異,居然都是意外死亡仲吏,警方通過查閱死者的電腦和手機不铆,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門蝌焚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人誓斥,你說我怎么就攤上這事只洒。” “怎么了劳坑?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵毕谴,是天一觀的道長。 經常有香客問我距芬,道長涝开,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任框仔,我火速辦了婚禮舀武,結果婚禮上,老公的妹妹穿的比我還像新娘离斩。我一直安慰自己银舱,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布跛梗。 她就那樣靜靜地躺著寻馏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪核偿。 梳的紋絲不亂的頭發(fā)上诚欠,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音宪祥,去河邊找鬼聂薪。 笑死,一個胖子當著我的面吹牛蝗羊,可吹牛的內容都是我干的藏澳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼耀找,長吁一口氣:“原來是場噩夢啊……” “哼翔悠!你這毒婦竟也來了?” 一聲冷哼從身側響起野芒,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤蓄愁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后狞悲,有當地人在樹林里發(fā)現了一具尸體撮抓,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年摇锋,在試婚紗的時候發(fā)現自己被綠了丹拯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片站超。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖乖酬,靈堂內的尸體忽然破棺而出死相,到底是詐尸還是另有隱情,我是刑警寧澤咬像,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布算撮,位于F島的核電站,受9級特大地震影響县昂,放射性物質發(fā)生泄漏肮柜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一七芭、第九天 我趴在偏房一處隱蔽的房頂上張望素挽。 院中可真熱鬧,春花似錦狸驳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酥馍,卻和暖如春辩昆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旨袒。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工汁针, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砚尽。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓施无,卻偏偏與公主長得像,于是被迫代替她去往敵國和親必孤。 傳聞我的和親對象是個殘疾皇子猾骡,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容

  • 回流和重繪可以說是每一個web開發(fā)者都經常聽到的兩個詞語,可是可能有很多人不是很清楚這兩步具體做了什么事情敷搪。最近有...
    java菜閱讀 480評論 0 1
  • 本文參考:你真的了解回流和重繪嗎 瀏覽器的渲染過程 解析HTML兴想,生成DOM樹,解析CSS赡勘,生成CSSOM樹 將D...
    kevision閱讀 197評論 0 1
  • 瀏覽器的渲染過程 從上面這個圖上闸与,我們可以看到毙替,瀏覽器渲染過程如下: 解析HTML曼振,生成DOM樹,解析CSS蔚龙,生成...
    MosnChina閱讀 175評論 0 0
  • 回流和重繪可以說是每一個web開發(fā)者都經常聽到的兩個詞語冰评,我也不例外,可是我之前一直不是很清楚這兩步具體做了什么事...
    橙贖閱讀 244評論 0 0
  • 久違的晴天木羹,家長會甲雅。 家長大會開好到教室時,離放學已經沒多少時間了坑填。班主任說已經安排了三個家長分享經驗抛人。 放學鈴聲...
    飄雪兒5閱讀 7,495評論 16 22