天天看點

高性能JavaScript之重繪和重排

浏覽器下載下傳完頁面所需的所有元件後就開始解析并生成兩個内部資料結構:

  • DOM樹:表示頁面結構
  • 渲染樹:表示 DOM 節點如何展示

DOM 樹中的每個需要顯示的節點在渲染樹中至少存在一個對應的節點(隐藏的DOM 元素沒有)。渲染樹中的節點被稱為“幀”或“盒”,符合 CSS 模型的定義(盒子模型是一個具有内邊距,外邊距,邊框和位置的盒子)。一旦 DOM 和渲染樹建構完成,浏覽器就開始顯示頁面元素。

  • 重排(回流):浏覽器需要重新計算元素的幾何屬性,需要重新構造渲染樹。
  • 重繪:重新繪制元素

重排何時發生?一句話總結:當頁面布局和幾何屬性發生改變時需要重排

  • 添加或者删除元素
  • 改變元素的幾何尺寸(padding,margin,border,height,width等)
  • 元素位置改變
  • 内容改變(文本改變或者圖檔被另個一尺寸的圖檔代替)
  • 浏覽器的視窗發生改變
  • 滾動條滾動時

渲染樹變化的排隊與重新整理:

由于每次重排都會産生計算消耗,大多數浏覽器通過隊列化修改和批量執行來優化重排過程。擷取布局的資訊會導緻隊列重新整理,比如以下方法:

  • offsetTop,offsetLeft,offsetWidth,offsetHeight
  • scrollTop,scrollLeft,scrollWidth,scrollHeight
  • clientTop,clientLeft,clientWidth,clientHeight

最小化重排和重繪:

  • 改變樣式:
var el = document.getElementById('div');
el.style.borderLeft = '2px';
el.sytle.borderRight = '2px';
el.style.padding = '2px';
// 需改為
var el = document.getElementById('div');
el.style.cssText = 'border-left: 2px; border-right: 2px; padding: 2px;';
           
  • 批量修改 DOM

    使用以下方式可以較少重排和重繪的次數。

    1. 使元素脫離文檔流
    2. 對其應用多重改變
    3. 再把元素帶回文檔中

    這個過程隻有第一步和第三部發生重排,第二步無論修改多少次都不影響。

    有三種方式可以使 DOM 脫離文檔:

    • 隐藏元素,應用修改,重新顯示
    • 使用文檔片段在目前 DOM 之外建構一個子樹,再把它拷貝回來(推薦)
    • 将原始元素拷貝到一個脫離文檔的節點中,修改副本,完成後再替換原始元素

繼續閱讀