1. 程式人生 > 其它 >DOM操作影響頁面的效能(重排重繪) ——轉載

DOM操作影響頁面的效能(重排重繪) ——轉載

1.頁面的渲染過程

(1)Javascript:通過JS實現動畫效果或者操作DOM實現互動

(2)Style:計算樣式,如果樣式有改變將重新計算,並返回給DOM

(3)Layout:根據DOM的樣式,重新佈局(重排)

(4)Paint:在多個渲染層上,對新的佈局重新渲染(重繪)

(5)Composite:將繪製好的多個渲染層合併,顯示到頁面上

在頁面生成時,至少進行一次佈局和渲染,在後面使用者不斷地操作過程中會進行多次的重排和重繪,以至於影響頁面的效能。

2.通過JS操作DOM影響頁面效能的問題有

(1)訪問和修改DOM

(2)修改DOM元素的樣式,導致重繪或者重排

(3)通過對DOM元素的事件處理,完成與使用者的互動功能

3.DOM操作對頁面效能的影響

(1)DOM的修改會導致重排和重繪

重排是指元素的位置或者大小發生了改變,瀏覽器需要重新去計算渲染樹,新的渲染樹建立之後,瀏覽器會重新繪製所影響的元素

重繪是指元素的樣式發生了變化,而大小和尺寸沒有發生改變

(2)導致頁面重排的一些操作

  • 內容改變:文字改變或者圖片的尺寸改變
  • DOM元素的幾何屬性改變:元素的寬高改變時,原來渲染樹中的DOM節點會失效,瀏覽器會根據DOM的變化重新構建渲染樹中的相關節點。如果父元素的幾何屬性發生變化時,會導致子元素以及兄弟元素的位置發生變化,從而引起重排。
  • DOM樹結構發生變化:新增DOM節點,修改DOM節點的位置以及刪除某個節點都會對渲染樹進行修改,從而導致重排。瀏覽器的佈局是自上而下的,修改當前元素不會都之前的元素造成影響,但是會對之後的元素造成影響,導致重排。
  • 獲取某些屬性時:當獲取一些屬性值時,瀏覽器為了保證獲取到正確的值也會引起重排。如元素的offsetTop,offsetLeft,offsetHeight,offsetWidth,scrollTop,scrollWidth,scrollLeft,scrollHeight、
  • 瀏覽器視窗尺寸發生改變時:瀏覽器視窗的尺寸發生改變時,會導致所有元素的尺寸發生變化,從而導致重排。

(3)導致頁面重繪的一些操作

只修改元素的樣式,而未修改元素的大小和位置,引起重繪

重排一定引起重繪,而重繪不一定引起重排

4.效能優化

(1)瀏覽器本身的優化策略

瀏覽器會維護一個佇列,將所有引起重排和重繪的操作都放在這個佇列裡,當操作達到一定的數量或者時間間隔時,瀏覽器會進行一個批處理。這樣可以讓多次的重排重繪,變成一次。但是有時候一些特殊的style屬性會使這種優化失效,例如offsetTop,scrollTop,clientTop等屬性,這些屬性都是要實時返回給使用者的

幾何屬性或者佈局屬性,因此瀏覽器需要立即執行,觸發重排返回正確的值。

(2)最小化的重排和重繪

減少對渲染樹的操作,並減少對一些style資訊的請求。

  • 將多次樣式改變屬性合併成一次操作(僅適用於單個節點)
  •  
    //javascript
     
    var el = document.getElementById("el");
     
    el.style.color = "red";
     
    el.style.height = "100px";
     
    el.style.width = "20px";
  • 可以使用內聯樣式的cssText實現

  • var el = document.getElementById("el");
     
    el.style.cssText = 'color: red; height:100px; width:20px'
    還可以使用切換類名的方法 
    
     
    //CSS
     
    .active{
     
    color: red;
     
    width: 20px;
     
    height: 100px;
     
    }
     
    //javascript
     
    var el = document.getElementById("el");
     
    el.className = "active";
  • 批量修改DOM

核心思想:

讓元素脫離文字流;對其進行多重改變;將元素帶回文件中;

a. 採用display屬性隱藏元素,修改之後再顯示元素,這樣只在顯示和隱藏元素是觸發兩次重排; 將多次需要重排元素,position屬性設定為absolute和fixed這樣就脫離文件流,元素的變化將不會影響其他元素。使用動畫效果的元素最好設定成絕對定位。

b. 使用文件片段建立一個子樹,然後再拷貝到文件中。例如要一步獲取一個列表中的元素,可以在記憶體中生成一個列表的HTML片段,然後再一次新增到文件中,而不是每迴圈一次新增一項。這樣就只觸發了一次重排。

c. 將原始元素拷貝到一個獨立節點中去,然後操作這個獨立的節點,覆蓋原始元素。

  • 快取佈局資訊

當訪問offsetTop這種屬性時,會衝破瀏覽器本身的優化,所以應減少對佈局資訊的查詢。可以將屬性值賦值給區域性變數來參與運算。

 
var a = el.offsetWidth;
 
a.style.width = 1 + ++a +'px';

原作者——https://blog.csdn.net/qq_41993503/article/details/98366177