天天看點

《高性能javascript》 領悟随筆之-------DOM程式設計篇(二)

《高性能javascript》 領悟随筆之-------DOM程式設計篇二

  序:在javaSctipt中,ECMASCRIPT規定了它的文法,BOM實作了頁面與浏覽器的互動,而DOM則承載着整個頁面文檔。DOM程式設計性能一直以來都是非常受開發者關注的話題,如何編寫高性能的DOM是前端開發必不可少的技能。

 1.重繪與重排

  當浏覽器加載完頁面所有的元素、js、css、圖檔之後會自動生成兩個資料結構:

1.dom樹

《高性能javascript》 領悟随筆之-------DOM程式設計篇(二)

(圖檔為轉載)

如圖所示,dom樹表示了整個頁面文檔的結構,通過通路dom樹我們可以得到某個元素,并且操作這個元素;

2.渲染樹

  表示dom節點如何顯示;

《高性能javascript》一書中是這麼描述的:dom樹中每一個需要顯示的節點在渲染樹中至少存在一個對應的節點(隐藏的dom元素在渲染樹中沒有對應的節點)。渲染樹中的節點被稱為 “幀(frams)” 或 “盒(boxes)”,符合css模型的定義,了解頁面元素為一個具有内邊距(padding),外邊距(margins),邊框(borders)和位置(position)的盒子。一旦dom和渲染樹建構完成,浏覽器就開始顯示頁面元素。

  參考  http://blog.csdn.net/greenqingqingws/article/details/19822139  詳細闡述了

【浏覽器渲染原理】渲染樹建構之渲染樹和DOM樹的關系;

當我們去修改元素的屬性,比如寬度、高度、動态增加文字、就會引起浏覽器的“重排 與 重繪”,減少它發生的次數是提高dom性能的關鍵之一;

那麼如何減少 “重排 與 重繪” 發生的次數呢?

3.合并多次對dom和樣式的修改,然後一次性處理掉;

一個栗子:

var el = document.getElementById('mydiv');
el.style.color='red';
el.style.padding='5px';
el.style.borderLeft = "1px solid red";      

這個栗子中div有三個元素樣式的改變,每一個都會影響元素的結構,這種情況會導緻在某些浏覽器下頁面觸發三次重排,這麼做效率是非常低下的;

将css集中修改:csstext 方法,它可以以字元串的形式一次性修改css樣式資訊,需要注意的是它會覆寫已存在的行間樣式資訊;

var el = document.getElementById('mydiv');
var csstext = "color:red;border-right:1px solid red;padding:5px;";


//集中一次性修改樣式 
el.style.cssText += csstext;      

還可以使用添加删除class名稱達到同樣的效果,通過class名得到的性能會更好,在不同的應用場景應首先考慮增删class名的修改方法;

4.批量修改dom;

當我們通過ajax請求得到一個清單資料的時候,我們需要循環将資料插入到頁面中。如果每次循環插入一個節點的話,那頁面很可能會直接崩潰掉,我們要避免這個問題的發生;

文檔片段(document.createDocumentFragment());

建立一個隐式的副本,看栗子

//建立一個fragment臨時dom存儲空間
var fragment= document.createDocumentFragment();

for(......){
 var div =  document.createElement("div");
........
//将div存儲在fragment臨時空間中
          fragment.appendChild(div);
}
//将組裝好的dom塞進body
document.body.appendChild(fragment);      

此方法隻插入一次,完成所有的dom更新工作,是dom操作性能的關鍵之一  (innerHTML同理)

                                   

2.事件委托

每多綁定一個事件處理程式都會加重頁面的性能負擔,簡單優雅的操作應該使用 “事件委托”。 它基于事件冒泡機制;通過監聽父級元素的事件,判斷出事件的來源元素;

《高性能javascript》 領悟随筆之-------DOM程式設計篇(二)

當我們點選div,div觸發click事件,事件被冒泡到body body觸發click事件直到文檔根document;

假如要給頁面中的每一個a元素添加一個點選事件,我們可以這樣做:

document.addEventListener("click",function(ev){
        var Event = ev||window.event;
        if(Event.target.nodeName=="A"){
            alert("點選了a标簽");
        }
    },false);      

當a點選被冒泡到document的時候,判斷它的來源,如果是a則執行相應的代碼,這就是事件委托的概念;

在jQuery中事件冒泡被封裝在.on()方法裡 , 可以更簡單的使用它:

$(document).on("click","a",function(){
        alert("這是一個a标簽");
 });      

更多關于事件委托  參考:http://www.cnblogs.com/leejersey/p/3801452.html 

js中的事件委托

3.dom篇總結

1.最小化通路dom的次數,盡可能使用javascript處理;

2.如果多次通路一個dom節點,需要儲存局部變量中;

3.處理html集合最好的方法是将他們複制到一個臨時的數組中,數組的通路速度要比dom快的多;

4.使用事件委托

--------------學無止境,站在巨人的肩上才能看的更高、更遠--------------

========================================================

轉載請注明出處。

繼續閱讀