javascript dom 操作最佳化

來源:互聯網
上載者:User

DOM 操作最佳化
首先澄清兩個概念——Repaint 和 Reflow:Repaint 也叫 Redraw,它指的是一種不會影響當前 DOM 的結構和布局的一種重繪動作。如下動作會產生 Repaint 動作:
不可見到可見(visibility 樣式屬性);
顏色或圖片變化(background, border-color, color 樣式屬性);
不改變頁面元素大小,形狀和位置,但改變其外觀的變化
Reflow 比起 Repaint 來講就是一種更加顯著的變化了。它主要發生在 DOM 樹被操作的時候,任何改變 DOM 的結構和布局都會產生 Reflow。但一個元素的 Reflow 操作發生時,它的所有父元素和子項目都會放生 Reflow,最後 Reflow 必然會導致 Repaint 的產生。舉例說明,如下動作會產生 Reflow 動作:
瀏覽器視窗的變化;
DOM 節點的添加刪除操作
一些改變頁面元素大小,形狀和位置的操作的觸發 通過 Reflow 和 Repaint 的介紹可知,每次 Reflow 比其 Repaint 會帶來更多的資源消耗,因此,我們應該盡量減少 Reflow 的發生,或者將其轉化為只會觸發 Repaint 操作的代碼。

 代碼如下 複製代碼
var tipBox = document.createElement('div');
document.body.appendChild('tipBox');//reflow
var tip1 = document.createElement('div');
var tip2 = document.createElement('div');
tipBox.appendChild(tip1);//reflow
tipBox.appendChild(tip2);//reflow

如上的代碼,會產生三次reflow,最佳化後的代碼如下:

 代碼如下 複製代碼
var tipBox = document.createElement('div');
   tip1 = document.createElement('div');
   tip2 = document.createElement('div');
tipBox.appendChild(tip1);
tipBox.appendChild(tip2);
document.body.appendChild('tipBox');//reflow

當然還可以利用 display 來減少reflow次數

 代碼如下 複製代碼
var tipBox = document.getElementById('tipBox');
tipBox.style.display = 'none';//reflow
tipBox.appendChild(tip1);
tipBox.appendChild(tip2);
tipBox.appendChild(tip3);
tipBox.appendChild(tip4);
tipBox.appendChild(tip5);
tipBox.style.width = 120;
tipBox.style.height = 60;
tipBox.style.display = 'block';//reflow

DOM元素測量屬性和方法也會觸發reflow,如下:

 代碼如下 複製代碼
var tipWidth = tipBox.offsetWidth;//reflow
   tipScrollLeft = tipBox.scrollLeft;//reflow
   display = window.getComputedStyle(div,'').getPropertyValue('display');//reflow

觸發reflow的屬性和方法大概有這些:

 代碼如下 複製代碼
offsetLeft
offsetTop
offsetHeight
offsetWidth
scrollTop/Left/Width/Height
clientTop/Left/Width/Height
getComputedStyle()
currentStyle(in IE))

我們可以用臨時變數將“offsetWidth”的值緩衝起來,這樣就不用每次訪問“offsetWidth”屬性。這種方式在迴圈裡面非常適用,可以極大地提高效能。
如果有批量的樣式屬性需要修改,建議通過替換className的方式來降低reflow的次數,曾經有這樣一個情境:有三個intput,分別對應下面三個圖片和三個內容地區,第二input選中的時候,第二圖片顯示,其他圖片隱藏,第二塊內容顯示,其他內容隱藏,直接操作DOM節點的代碼如下

 代碼如下 複製代碼

var input = [];
   pics = [];
   contents = [];
......
inputFrame.onclick =function(e){
    var _e,_target;
    _e = e ? window.event : null;
    if(!_e){
      return;
   }else{
     _target = _e.srcElement || _e.target ;
     _index = getIndex(_target);//reflow兩次
    show(_target,_index);//reflow兩次
   }

}
function show(target,j){
 for(var i = 0,i<3;i++){
  target[i].style.display = 'none';//reflow
 }
 target[j].style.display = 'block';//reflow
}
function getIndex(targer){
    if(target){
    .....//擷取當前的元素索引
    return index;
    }
}


如果是通過css預先定義元素的隱藏和顯示,通過對父級的className進行操縱,將會把reflow的次數減少到1次

 代碼如下 複製代碼
.pbox .pic,.pbox content{display:none}
.J_pbox_0 .pic0,.J_pbox_0 .content0{diplay:block}
.J_pbox_1 .pic1,.J_pbox_1 .content1{diplay:block}
.J_pbox_2 .pic2,.J_pbox_2 .content2{diplay:block}
var input = [],
   parentBox = document.getELementById('J_Pbox');
......
inputFrame.onclick =function(e){
    var _e,_target;
    if(){
     ...
    }else{
     ...
      parentBox.className = 'pbox J_pbox_'+_infex;//reflow一次
    }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.