1.瀏覽器自身所作的優化
2.如何優化你的腳本來減少repaint/reflow?
一.瀏覽器優化
瀏覽器對於每一個渲染動作並不是立即執行,而是維護了一個渲染任務隊列,瀏覽器會根據具體的需要分批集中執行其中的任務。除了瀏覽器自身維護的定期調度之外,腳本中的某些操作會導致瀏覽器立即執行渲染任務,例如讀取元素的Layout屬性。
var bodystyle = document.body.style;
var computed;
if (document.body.currentStyle) {
computed = document.body.currentStyle;
} else {
computed = document.defaultView.getComputedStyle(document.body, '');
}
//每次都讀取
bodystyle.color = 'red';
bodystyle.padding = '1px';
tmp = computed.backgroundColor;
bodystyle.color = 'white';
bodystyle.padding = '2px';
tmp = computed.backgroundImage;
bodystyle.color = 'green';
bodystyle.padding = '3px';
tmp = computed.backgroundAttachment;
//最後再讀取
bodystyle.color = 'yellow';
bodystyle.padding = '4px';
bodystyle.color = 'pink';
bodystyle.padding = '5px';
bodystyle.color = 'blue';
bodystyle.padding = '6px';
tmp = computed.backgroundColor;
tmp = computed.backgroundImage;
tmp = computed.backgroundAttachment;
每次讀取的渲染圖:
最後讀取的渲染圖:
二、如何優化你的腳本來減少reflow/repaint?
1. 避免在document上直接進行頻繁的DOM操作,如果確實需要可以採用off-document的方式進行,具體的方法包括但不完全包括以下幾種:
(1). 先將元素從document中刪除,完成修改後再把元素放回原來的位置
(2). 將元素的display設置爲”none”,完成修改後再把display修改爲原來的值
(3). 如果需要創建多個DOM節點,可以使用DocumentFragment創建完後一次性的加入document
function appendEveryTime(){
for( var i = 5000; i--; ){
var n = document.createElement('div');
n.innerHTML = 'node ' + i;
document.body.appendChild(n);/*每次創建的新節點都append到文檔*/
}
}
function appendLast(){
var frag = document.createDocumentFragment();
for( var i = 5000; i--; ){
var n = document.createElement('div');
n.innerHTML = 'node ' + i;
frag.appendChild(n);/*每次創建的節點先放入DocumentFragment中*/
}
document.body.appendChild(frag);
}
用dynaTrace觀察的結果如下,appendLast的性能無論是在Javascript的執行時間以及瀏覽器渲染時間方面都優於appendEveryTime。
appendEveryTime:
appendLast:
2. 集中修改樣式
(1). 儘可能少的修改元素style上的屬性
(2). 儘量通過修改className來修改樣式
(3). 通過cssText屬性來設置樣式值
如下的代碼中,每一次賦值都會造成瀏覽器重新渲染,可以採用cssText或者className的方式
el.style.color = 'red;
el.style.height = '100px';
el.style.fontSize = '12px';
el.style.backgroundColor = 'white';
3. 緩存Layout屬性值
對於Layout屬性中非引用類型的值(數字型),如果需要多次訪問則可以在一次訪問時先存儲到局部變量中,之後都使用局部變量,這樣可以避免每次讀取屬性時造成瀏覽器的渲染。
var width = el.offsetWidth;
var scrollLeft = el.scrollLeft;
4. 設置元素的position爲absolute或fixed
在元素的position爲static和relative時,元素處於DOM樹結構當中,當對元素的某個操作需要重新渲染時,瀏覽器會渲染整個頁面。將元素的position設置爲absolute和fixed可以使元素從DOM樹結構中脫離出來獨立的存在,而瀏覽器在需要渲染時只需要渲染該元素以及位於該元素下方的元素,從而在某種程度上縮短瀏覽器渲染時間,這在當今越來越多的Javascript動畫方面尤其值得考慮。
HTML代碼:
Animation Here
Javascript代碼:
var t = $('test');
~function(){
t.style.left = t.offsetLeft + 5 + 'px';
t.style.height = t.offsetHeight + 5 + 'px';
setTimeout(arguments.callee,500);
}();
通過修改#test元素的postion爲relative和postion分別得到如下兩個測試結果
position: relative
position: absolute
在postion:relative的測試當中,瀏覽器在重新渲染時做的工作比position:absolute多了不少。