2018-09-13 回流reflow 重繪repaint 重排reflows

  • 瀏覽器加載時(shí)會(huì)發(fā)生什么

    詳情可以查看這篇文章
    首先瀏覽器會(huì)解析html 生成DOM樹;
    接下來瀏覽器會(huì)將CSS部分解析成樣式結(jié)構(gòu)體;
    完成以上兩步之后將 dom tree 和樣式結(jié)構(gòu)體結(jié)合,生成render tree;
    在render tree生成后 瀏覽器開始繪制頁面。
    需要注意的是
    不會(huì)用于呈現(xiàn),而且不會(huì)影響呈現(xiàn)的隱藏節(jié)點(diǎn)不會(huì)包含到render tree
    例如display:none,而visibility:hidden則會(huì)包含到render tree;

  • 回流何時(shí)發(fā)生的?

    首先要明確

    1. 頁面至少會(huì)發(fā)生一次回流
    2. 回流必定重繪,重繪不一定回流

    下面所有都會(huì)引起回流

    1. 調(diào)整窗口大小(Resizing the window)
    2. 改變字體(Changing the font)
    3. 增加或者移除樣式表(Adding or removing a stylesheet)
    4. 內(nèi)容變化,比如用戶在input框中輸入文字(Content changes, such as a user typing text inan input box)
    5. 激活 CSS 偽類,比如 :hover (IE 中為兄弟結(jié)點(diǎn)偽類的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
    6. 操作 class 屬性(Manipulating the class attribute)
    7. 腳本操作 DOM(A script manipulating the DOM)
    8. 計(jì)算 offsetWidth 和 offsetHeight 屬性(Calculating offsetWidth and offsetHeight)
    9. 設(shè)置 style 屬性的值 (Setting a property of the style attribute)
      原文鏈接:回流與重繪:CSS性能讓JavaScript變慢?
  • 如何減少回流帶來的影響,優(yōu)化性能

    1. 如果想設(shè)定元素的樣式,通過改變?cè)氐?class 名 (盡可能在 DOM 樹的最末端)(Change classes on the element you wish to style (as low in the dom tree as possible))
    2. 避免設(shè)置多項(xiàng)內(nèi)聯(lián)樣式(Avoid setting multiple inline styles)
    3. 應(yīng)用元素的動(dòng)畫,使用 position 屬性的 fixed 值或 absolute 值(Apply animations to elements that are position fixed or absolute)
    4. 權(quán)衡平滑和速度(Trade smoothness for speed)
    5. 避免使用table布局(Avoid tables for layout)
    6. 避免使用CSS的JavaScript表達(dá)式 (僅 IE 瀏覽器)(Avoid JavaScript expressions in the CSS (IE only))
      原文鏈接:回流與重繪:CSS性能讓JavaScript變慢?
  • 重繪repaint 重排reflows

    重繪repaint 是一個(gè)元素外觀的改變所觸發(fā)的瀏覽器行為,例如改變vidibility、outline、背景色等屬性。瀏覽器會(huì)根據(jù)元素的新屬性重新繪制,使元素呈現(xiàn)新的外觀。重繪不會(huì)帶來重新布局,并不一定伴隨重排。
    重排reflows 是更明顯的一種改變,可以理解為渲染樹需要重新計(jì)算。下面是常見的觸發(fā)重排的操作

  1. DOM元素的幾何屬性變化
    當(dāng)DOM元素的幾何屬性變化時(shí),渲染樹中的相關(guān)節(jié)點(diǎn)就會(huì)失效,瀏覽器會(huì)根據(jù)DOM元素的變化重建構(gòu)建渲染樹中失效的節(jié)點(diǎn)。之后,會(huì)根據(jù)新的渲染樹重新繪 制這部分頁面。而且,當(dāng)前元素的重排也許會(huì)帶來相關(guān)元素的重排。例如,容器節(jié)點(diǎn)的渲染樹改變時(shí),會(huì)觸發(fā)子節(jié)點(diǎn)的重新計(jì)算,也會(huì)觸發(fā)其后續(xù)兄弟節(jié)點(diǎn)的重排, 祖先節(jié)點(diǎn)需要重新計(jì)算子節(jié)點(diǎn)的尺寸也會(huì)產(chǎn)生重排。最后,每個(gè)元素都將發(fā)生重繪??梢?,重排一定會(huì)引起瀏覽器的重繪,一個(gè)元素的重排通常會(huì)帶來一系列的反 應(yīng),甚至觸發(fā)整個(gè)文檔的重排和重繪,性能代價(jià)是高昂的。
  2. DOM樹的結(jié)構(gòu)變化
    當(dāng)DOM樹的 結(jié)構(gòu)變化時(shí),例如節(jié)點(diǎn)的增減、移動(dòng)等,也會(huì)觸發(fā)重排。瀏覽器引擎布局的過程,類似于樹的前序遍歷,是一個(gè)從上到下從左到右的過程。通常在這個(gè)過程中,當(dāng)前 元素不會(huì)再影響其前面已經(jīng)遍歷過的元素。所以,如果在body最前面插入一個(gè)元素,會(huì)導(dǎo)致整個(gè)文檔的重新渲染,而在其后插入一個(gè)元素,則不會(huì)影響到前面的 元素。
    3.** 獲取某些屬性**
    瀏覽器引擎可能會(huì)針對(duì)重排做了優(yōu)化。比如Opera,它會(huì)等到有足夠 數(shù)量的變化發(fā)生,或者等到一定的時(shí)間,或者等一個(gè)線程結(jié)束,再一起處理,這樣就只發(fā)生一次重排。但除了渲染樹的直接變化,當(dāng)獲取一些屬性時(shí),瀏覽器為取得 正確的值也會(huì)觸發(fā)重排。這樣就使得瀏覽器的優(yōu)化失效了。這些屬性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用這些值時(shí)應(yīng)進(jìn)行緩存。
    此外,改變?cè)氐囊恍邮剑{(diào)整瀏覽器窗口大小等等也都將觸發(fā)重排。
    開發(fā)中,比較好的實(shí)踐是盡量減少重排次數(shù)和縮小重排的影響范圍。
如何減少重排帶來的影響
  1. 將多次改變樣式屬性的操作合并成一次操作。
  2. 將需要多次重排的元素,position屬性設(shè)為absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會(huì)影響到其他元素。例如有動(dòng)畫效果的元素就最好設(shè)置為絕對(duì)定位。
  3. 在內(nèi)存中多次操作節(jié)點(diǎn),完成后再添加到文檔中去。例如要異步獲取表格數(shù)據(jù),渲染到頁面。可以先取得數(shù)據(jù)后在內(nèi)存中構(gòu)建整個(gè)表格的html片段,再一次性添加到文檔中去,而不是循環(huán)添加每一行。
  4. 由于display屬性為none的元素不在渲染樹中,對(duì)隱藏的元素操作不會(huì)引發(fā)其他元素的重排。如果要對(duì)一個(gè)元素進(jìn)行復(fù)雜的操作時(shí),可以先隱藏它,操作完成后再顯示。這樣只在隱藏和顯示時(shí)觸發(fā)2次重排。
  5. 在需要經(jīng)常取那些引起瀏覽器重排的屬性值時(shí),要緩存到變量。

相關(guān)鏈接.

頁面重繪和回流以及優(yōu)化
瀏覽器的重繪(repaints)與重排(reflows)

最后編輯于
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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