repaint&reflow

HTML頁面呈現(xiàn)流程

HTML 頁面呈現(xiàn)的流程
  1. 瀏覽器將獲取到的HTML代碼解析成DOM樹,其中的每個(gè)Tag標(biāo)簽都是一個(gè)節(jié)點(diǎn)。DOM樹中包含所有HTML標(biāo)簽,包括display:none隱藏,還有用JS動(dòng)態(tài)添加的元素等。
  2. 瀏覽器將CSS樣式解析成樣式結(jié)構(gòu)體,該過程中會(huì)去掉瀏覽器不能識(shí)別的樣式,如IE會(huì)去掉-moz開頭的樣式。
  3. DOM Tree和樣式結(jié)構(gòu)體組合后構(gòu)建Render Tree.

Render Tree和DOM Tree的區(qū)別:

  • Render Tree能識(shí)別樣式,其中的每個(gè)Node都有自己的style。
  • Render Tree不包含隱藏的節(jié)點(diǎn),比如display:none的節(jié)點(diǎn),還有head節(jié)點(diǎn)。因?yàn)檫@些節(jié)點(diǎn)不用于呈現(xiàn),而且會(huì)影響呈現(xiàn)。visibility:hidden;占有空間,會(huì)包含在其中。
  • Render Tree中每個(gè)節(jié)點(diǎn)都稱為盒模型。
  1. 一旦Render Tree構(gòu)建完畢,瀏覽器就會(huì)根據(jù)Render Tree來繪制頁面了。

重繪和回流

當(dāng)Render Tree中的一部分因?yàn)樵氐囊?guī)模尺寸,布局等改變而需要重新構(gòu)建(頁面布局或幾何屬性改變時(shí)就需要回流),就稱為回流reflow。也稱重排。

每個(gè)頁面至少需要一次回流,就是在頁面加載的時(shí)候。
在回流的時(shí)候,瀏覽器會(huì)使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹,完成回流后,瀏覽器會(huì)重新繪制受影響的部分到屏幕中,該過程稱為重繪repaint。

當(dāng)Render Tree中的一些元素需要更新屬性,而這些屬性只影響元素的外觀,風(fēng)格,而不影響布局,如background-color,則就稱重繪。

回流必將引起重繪,而重繪不一定引起回流?;亓鞯拇鷥r(jià)要比重繪高很多。

瀏覽器的處理

瀏覽器會(huì)維護(hù)一個(gè)隊(duì)列,將所有會(huì)引起回流,重繪的操作放入這個(gè)隊(duì)列,等隊(duì)列中的操作到了一定數(shù)量或到了一定的時(shí)間間隔,瀏覽器就會(huì)flush隊(duì)列,進(jìn)行一個(gè)批處理。這樣就會(huì)讓多次的回流、重繪變成一次回流重繪。

當(dāng)你請(qǐng)求一些屬性時(shí),瀏覽器為了給你最精確的值,就會(huì)提前flush隊(duì)列。

如何減少回流,重繪

本質(zhì)是減少對(duì)Render Tree的操作,合并多次多DOM和樣式的修改,并減少對(duì)style信息的請(qǐng)求,盡量利用好瀏覽器的優(yōu)化策略。

  1. 直接改變className,如果動(dòng)態(tài)改變樣式,使用cssText.
let box = document.getElementById('box');
// 不好
box.style.backgroundColor = 'red';
box.style.width = '10px';
// 正確
box.style.cssText += 'background-color:red;width:10px;';

cssText可以使用累加,這樣原來的cssText不會(huì)被刪除;

cssText(假如不為空)在IE中最后一個(gè)分號(hào)會(huì)被刪掉,因此,上面cssText累加的方法在IE中是無效的??梢栽谇懊嫣砑右粋€(gè)分號(hào)來解決這個(gè)問題:box.style.cssText += ';background-color:red;width:10px;';

  1. 讓要操作的元素進(jìn)行“離線處理”,處理完后一起更新。
  • 使用DocumentFragment進(jìn)行緩存操作,引發(fā)一次回流和重繪。
    <ul id="list"></ul> // 向ul里插入li
  let listNode = document.getElementById('list');
  let frag = document.createDocumentFragment();
  for (let i = 0; i < 10; i++) { // 將frag當(dāng)作ul進(jìn)行操作
    let li = document.createElement('li');
    li.innerHTML = 'List item ' + i;
    frag.appendChild(li);
  }
  listNode.appendChild(frag);  // 把DocumentFragement掛到它的父節(jié)點(diǎn)上
  • 使用display:none;技術(shù),只引發(fā)兩次回流和重繪。
  • 使用cloneNode(true or false)replaceChild技術(shù),引發(fā)一次回流和重繪。
  1. 不要經(jīng)常訪問會(huì)引起瀏覽器flush隊(duì)列的屬性,如果你確實(shí)要訪問,利用緩存。
  2. 讓元素脫離動(dòng)畫流,減少回流的Render Tree的規(guī)模。
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.appendChild(document.createTextNode('abc!'));

除了頁面在首次加載時(shí)必然經(jīng)歷回流和重繪,還有以下行為會(huì)觸發(fā)這個(gè)過程:

  • DOM元素的添加,修改,刪除(reflow+repaint)
  • 僅修改DOM元素的字體顏色(只有repaint)
  • 應(yīng)用新的樣式或修改任何影響元素外觀的屬性
  • resize瀏覽器窗口、滾動(dòng)頁面
  • 讀取元素的某些屬性(offsetLeft,offsetTop,offsetHeight,offsetWidth,scrollTop... ...)

參考資料:
http://www.css88.com/archives/4996
http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載說明 一、介紹 瀏覽器可以被認(rèn)為是使用最廣泛的軟件,本文將介紹瀏覽器的工作原理,我們將看到,從你在地址欄輸入g...
    17碎那年閱讀 2,525評(píng)論 0 22
  • 頁面重繪和回流以及優(yōu)化 在討論頁面重繪、回流之前。需要對(duì)頁面的呈現(xiàn)流程有些了解,頁面是怎么把html結(jié)合css等顯...
    sponing閱讀 2,129評(píng)論 1 11
  • 在討論頁面重繪、回流之前。需要對(duì)頁面的呈現(xiàn)流程有些了解,頁面是怎么把html結(jié)合css等顯示到瀏覽器上的,下面的流...
    抓住時(shí)間的尾巴吧閱讀 1,005評(píng)論 0 3
  • 在討論頁面重繪、回流之前。需要對(duì)頁面的呈現(xiàn)流程有些了解,頁面是怎么把html結(jié)合css等顯示到瀏覽器上的,下面的流...
    DavieKong閱讀 757評(píng)論 2 4
  • 引用自 Rendering: repaint, reflow/relayout, restyle 瀏覽器在下載好H...
    風(fēng)起云涌Hal閱讀 4,205評(píng)論 0 4

友情鏈接更多精彩內(nèi)容