在前端開發的過程中,性能優化是一個最常見的問題,重繪與重排也是提到優化時不可忽視的一塊。
那麼什麼是重繪與重排呢,在解釋重繪與重排之前,我們首先需要先了解清楚瀏覽器的渲染過程, 下面先上一張比較常見的渲染過程圖:
根據上圖我們可以看到和總結出瀏覽器的渲染大致分爲以下五個步驟:
-
DOM Tree: 瀏覽器根據HTML解析出DOM Tree
-
Style Rules:根據CSS解析出Style Rules
-
Render Tree: 將DOM Tree與Style Tree二者關聯生成Render Tree
-
Layout: 根據Render Tree計算每個節點的信息,即節點在屏幕上的顯示位置
-
Painting :根據計算好的信息繪製整個頁面
很多人在開發的過程中總是聽說,在瀏覽器的渲染過程中,DOM 的操作是最消耗性能的,爲什麼呢?因爲大部分的JavaScript DOM操作會導致一系列的重繪。
那麼什麼是重繪與重排呢:簡單來說,我的理解是,
重繪(repaint):當元素的外觀屬性發生變化,即元素的顏色,背景色發生改變但沒有影響到dom樹的位置改變的時候,會觸發重繪;
重排(reflow):當頁面內的元素尺寸發生了變化,導致部分或者全部DOM樹,渲染樹需要重新更新,會觸發重排, 重排又稱爲迴流;
一般情況下,頁面的重排必定會導致重繪,但重繪不一定會導致重排。
觸發重排的條件,具體來說有以下幾點:
1.頁面渲染初始化;
2.添加與刪除DOM元素;
3.元素位置的改變,或者使用動畫;
4.元素的尺寸發生改變;
5.瀏覽器窗口尺寸的變化(resize事件發生時);
6.文本內容被改變或者圖片被不同尺寸的圖片替換;
7.讀取某些元素屬性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )
一般在我們的開發過程中,當DOM元素的操作不可避免時, 我們可以通過以下方式來儘量減少重繪與重排,重點是減少重排,主要的思路是, 將多次的DOM 操作合併爲一次,或者使需要被操作的元素脫離文檔流以減少瀏覽器重繪與重排的次數,下面的這些操作都是通過減少重排重繪來實現性能優化的:
1.元素的多次樣式修改合併成一次修改;
2.如需進行對DOM節點進行多次操作,先將其脫離文本流之後再進行多次操作;
3.table佈局的渲染與普通DOM節點的操作相比,性能消耗更大,如果可以,儘量減少table佈局的使用;
4.緩存常用的佈局信息;
5.兼容IE時減少使用hover;
6.動畫使用window.requestAnimationFrame(),window.requestAnimationFrame() 這兩個方法調節重新渲染;
7.使用虛擬dom腳本庫,例如react或者snabbdom等。
參考鏈接:
網頁性能管理,重繪與重排:https://www.jianshu.com/p/f69b476a7200
dom操作爲什麼耗性能: https://segmentfault.com/a/1190000014070240