前端高階(二)重繪和回流

2021-08-20 18:34:11 字數 1880 閱讀 9395

今天結合專案說下重繪和回流。

公司**有個bug是這樣的:頁面整體分為三部分,頁面上面橫向併排兩個容器,頁面下方是個**。頁面上方兩個容器中圖形都是用highcharts畫的,但是頁面重繪導致其中乙個圖形在第二次回流時超出了容器邊界。這個問題我折騰了大半天都沒找到根源。最後才發現是下方**由於有多餘的邊框,有段js邏輯**是這樣寫的:

function clearborderright(source) );

}

這段**直接導致了頁面二次回流,使得dom發生變化,圖形衝破容器。

下面我將詳細分析造成重繪和回流的原因,首先我們先認識什麼叫重繪和回流。

一、回流和重繪基本概念

這個系列的第一篇文章詳細介紹了瀏覽器相關的原理,建議大家先看看。前端高階(一)瀏覽器執行原理

1、回流

當render樹中的一部分或者全部因為大小邊距等問題發生改變而需要重建的過程叫做回流(改變大小)。

2. 重繪

當元素的一部分屬性發生變化,如外觀背景色不會引起布局變化而需要重新渲染的過程叫做重繪(改變樣式)。

注意:回流必將引起重繪,而重繪不一定會引起回流。

二、回流和重繪發生條件

1、回流發生條件

當頁面布局和幾何屬性改變時就需要回流。下述情況會發生瀏覽器回流:

(1)新增或者刪除可見的dom元素;

(2)元素位置改變;

(3)元素尺寸改變——邊距、填充、邊框、寬度和高度

(4)內容改變——比如文字改變或者大小改變而引起的計算值寬度和高度改變;

(5)頁面渲染初始化;

(6)瀏覽器視窗尺寸改變——resize事件發生時;

2、重繪發生條件

元素的屬性或者樣式發生變化。

大家都知道回流的開銷較大,如果每個操作都去回流重繪的話,瀏覽器可能就會受不了。所以很多瀏覽器都會優化這些操作,瀏覽器會維護1個佇列,把所有會引起回流、重繪的操作放入這個佇列,等佇列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush佇列,進行乙個批處理。這樣就會讓多次的回流、重繪變成一次回流重繪。

雖然有了瀏覽器的優化,但有時一些**可能會強制瀏覽器提前flush佇列,這樣瀏覽器的優化可能就起不到作用了。當請求向瀏覽器請求一些 style資訊的時候,就會讓瀏覽器flush佇列,比如:

(1)offsettop, offsetleft, offsetwidth, offsetheight

(2) scrolltop/left/width/height

(3)clienttop/left/width/height

(4)width,height

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

三、如何減少回流和重繪

1、減少回流和重繪其實就是需要減少對render tree的操作(合併多次多dom和樣式的修改),並減少對一些樣式資訊的請求,盡量利用好瀏覽器的優化策略。

(1)新增css樣式而不是利用js控制樣式(我就是想到這種辦法解決回流問題的)

(2)盡量將需要改變dom的操作一次完成

(3)直接改變classname,如果動態改變樣式,則使用csstext(考慮沒有優化的瀏覽器)

(4)不要經常訪問會引起瀏覽器flush佇列的屬性,如果你確實要訪問,利用快取

(5)讓元素脫離動畫流,減少回流的render tree的規模

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

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

回流和重繪

在頁面載入時,瀏覽器把獲取到的html 解析成1個dom樹,dom樹里包含了所有html標籤,包括display none隱藏,還有用js動態新增的元素等。瀏覽器把所有樣式 使用者定義的css和使用者 解析成樣式結構體 dom tree 和樣式結構體組合後構建render tree 渲染樹 然後根據...

回流和重繪

html 載入過程 在頁面載入時,瀏覽器把獲取到的html 解析成1個dom樹,dom樹里包含了所有html標籤,包括display none隱藏,還有用js動態新增的元素等。瀏覽器把所有樣式 使用者定義的css和使用者 解析成樣式結構體 dom tree 和樣式結構體組合後構建render tre...

回流和重繪

回流 reflow 當render tree中的一部分 或全部 因為元素的規模尺寸 布局 隱藏等改變而需要重新構建,這就稱為回流。每個頁面至少需要回流一次,就是在頁面第一次載入的時候。重繪 repaint 當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀 風格,而不會影...