天天看點

重排VS重繪1.document.write和innerHtml2.DOM樹和渲染樹3.重排和重繪觸發重排的屬性重繪發生的情況優化

1.document.write和innerHtml

document.write // 重排整個頁面
innerHtml	//重繪頁面的某些部分
           

2.DOM樹和渲染樹

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

3.重排和重繪

重排:當DOM元素影響了元素的**幾何屬性**(例如寬和高),浏覽器需要重新計算元素的幾何屬性,
	 同樣其它元素的幾何屬性也會和位置也會是以受到影響。浏覽器會使渲染樹中受到影響的
	 部分失效,并重新構造渲染樹。 

重繪:完成重排後,浏覽器會重新繪制受影響的部分到螢幕上中。
           

重排發生的情況:

  • 頁面渲染器初始化。
  • 添加或删除可見的DOM元素。
  • 元素位置改變。
  • 元素的尺寸改變(包括:内外邊距、邊框厚度、寬度、高度等屬性的改變)。
  • 内容改變。
  • 浏覽器視窗尺寸改變。
  • 讀取某些元素屬性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE))

觸發重排的屬性

有些節點,當你改變他時,會需要重新布局(這也意味着需要重新計算其他被影響的節點的位置和大小)
這種情況下,被影響的DOM樹越大(可見節點),重繪所需要的時間就會越長,是以需要盡力避免這些屬
性。
           

一些常用的改變時會觸發重布局的屬性:

盒子模型相關屬性會觸發重布局:

  • width
  • height
  • padding
  • margin
  • display
  • border-width
  • border
  • min-height

定位屬性及浮動也會觸發重布局:

  • top
  • bottom
  • left
  • right
  • position
  • float
  • clear

改變節點内部文字結構也會觸發重布局:

  • text-align
  • overflow-y
  • font-weight
  • overflow
  • font-family
  • line-height
  • vertival-align
  • white-space
  • font-size

重繪發生的情況

重繪發生在元素的可見的外觀被改變,但并沒有影響到布局的時候。比如,僅修改DOM元素的
字型顔色(隻有Repaint,因為不需要調整布局)
           

觸發重繪的屬性

修改時隻觸發重繪的屬性有:

  • color
  • border-style
  • border-radius
  • visibility
  • text-decoration
  • background
  • background-image
  • background-position
  • background-repeat
  • background-size
  • outline-color
  • outline
  • outline-style
  • outline-width
  • box-shadow

注意:重排一定會引起重繪,但重繪不一定會引起重排。重排和重繪都會影響浏覽器性能。

優化

1.改變元素的className

例如:
// css 
	.active {
    padding: 5px;
    border-left: 1px;
    border-right: 2px;
	}
// javascript
	var el = document.querySelector('.el');
	el.className = 'active';
           

2.需要批量建立或修改多個DOM節點時:

1)隐藏元素,進行修改後,然後再顯示該元素

例如:
let ul = document.querySelector('#mylist');
ul.style.display = 'none';
appendNode(ul, data);
ul.style.display = 'block';

先将ul設定為display:none;然後進行頁面布局等操作;設定完成後将元素設定為
display:block;這樣的話就隻引發兩次重繪和重排,分别是控制元素的顯示與隐藏。
           

2)使用文檔片段建立一個子樹,然後再拷貝到文檔中

例如:
	let fragment = document.createDocumentFragment();
	appendNode(fragment, data);
	ul.appendChild(fragment);

文檔片段是一個輕量級的document對象,它設計的目的就是用于更新,移動節點之類的任務,
而且文檔片段還有一個好處就是,當向一個節點添加文檔片段時,添加的是文檔片段的子節點群,
自身不會被添加進去,這樣隻會觸發一次重排。
           

3)将原始元素拷貝到一個獨立的節點中,操作這個節點,然後覆寫原始元素

例如:
    let old = document.querySelector('#mylist');
    let clone = old.cloneNode(true);
    appendNode(clone, data);
    old.parentNode.replaceChild(clone, old);
    
這種方法也是隻有一次重排
           

3.緩存布局資訊

4.将需要多次重排的元素,position屬性設為absolute或fixed,元素脫離了文檔流,

它的變化不會影響到其他元素;

5.盡量不要使用table布局。

繼續閱讀