瀏覽器重排(迴流)重繪以及優化方案

1、什麼是重排和重繪

要說清重排(reflow)和重繪(repaint),首先要理解排列和繪製,瀏覽器渲染頁面時,在獲取完html、css資源以後,會大體通過如下步驟。
(1) html生成html樹
(2) css造成css規則
(3) 二者造成一個渲染樹
(4) 去文檔當中找尋各自的佈局位置----- 排列
(5) 將內容填充到文檔上 ----- 繪製
【排列】就是計算位置調整佈局的過程,而【繪製】就是把它畫上去的過程。【重排】也就是除了最開始排列的佈局,後續通過一些操做而使得dom元素從新找尋位置的過程,【重繪】就是從新繪製內容的過程。css

image

2、什麼狀況會引起重排和重繪

一、先來講重排,重排和位置的移動佈局的變化有關,主要有如下幾種狀況會引起重排
(1) 瀏覽器的窗口發生變化,每放大、縮小一次瀏覽器的窗口,該頁面的全部元素都要進行重排重繪
(2) 增長、刪除、移動dom元素,更改dom元素的寬高內外邊距、內容,修改dom元素的樣式
(3) 進行dom元素寬高等屬性的查詢,由於每查詢一次,瀏覽器都會對全部的元素進行從新計算,以確保計算的值是正確的html

二、再來講重繪,重繪主要是元素的外觀發生變化,不會從新佈局,有如下狀況會引起重繪
元素的背景(background)、文字顏色(color)、邊框樣式(outline)發生變化html5

三、重排和重繪的關係
重繪不必定須要重排,由於可能只是元素修改文字顏色,不須要從新佈局,重排大多數狀況都須要重繪,由於從新排列元素以後要繪製到屏幕上。node

如下顯示重排和重繪的耗時,方塊兩秒以後右移了100pxcss3

重繪重排過程.png

3、爲何要優化

由於重排和重繪不僅是對單個的dom元素進行操做,而是對整個【圖層】進行操做,須要花費時間,若是頻率高,很是的影響性能。chrome

那什麼是圖層?以下圖所示canvas

圖層.png

由於每一次的重排重繪都是操做整個圖層,那麼咱們能夠將須要頻繁操做的dom元素另外創建一個圖層,這樣能夠儘量少的觸發重排重繪。瀏覽器

那麼什麼狀況能夠開啓圖層?
針對頻繁操做的行爲,chrome瀏覽器自動開啓了圖層,主要有如下幾種狀況
一、css 3D變化的圖形 ---- transform: translateX(0)
二、html5中的<video>標籤
三、canvas繪圖中的節點
四、css 動畫的節點 --- keyframes animation
五、擁有css加速屬性 --- will-change: transformapp

除此以外,還可使用如下方式進行優化
一、對元素進行移動時,使用transform替代對元素top、left、right的操做,由於css3的整個操做是對圖層的組合來實現的,因此不會引起重繪重排。dom

#node{
  // position: relative; 
  transform: translateX(0);
  width: 100px;
  height: 100px;
  background: pink;
}
var node = document.querySelector("#node");
setTimeout(function(){
    //   node.style.left="100px";
   node.style.transform="translateX(100px)";
},2000);

一樣是對一個元素兩秒後移動100px,能夠看到對比下圖對比

重繪重排時間對比.png

二、將屢次對樣式的操做合併成一次
不要一次一次的修改樣式,而是預先定義好class,直接修改DOM的className,這樣只會引起一次重排重繪
三、將dom離線後修改
若是要對dom元素進行屢次操做,首先將dom設置爲不可見,而後再對dom操做,操做完成後再將dom元素設置爲可見,這樣只會有兩次重排重繪
四、利用文檔碎片 documentFragment
documentFragment 不是真實 dom樹的一部分,它的變化不會觸發dom樹的從新渲染,且不會致使性能等問題,將建立的新元素所有添加到documentFragment上,最後讓documentFragment一塊兒插入到dom元素中

const list = ['哈爾的移動城堡', '千與千尋的神隱', '起風了']
const ul = document.getElementsByTagName("ul")[0]
let fragment = document.createDocumentFragment()
for(let i in list){
    fragment.appendChild(list[i])
}
ul.appendChild(fragment)
相關文章
相關標籤/搜索