Javascript封裝DOMContentLoaded事件執行個體

來源:互聯網
上載者:User

   這篇文章主要介紹了Javascript封裝DOMContentLoaded事件執行個體,DOMContentLoaded是FF,Opera 9的特有的Event, 當所有DOM解析完以後會觸發這個事件,需要的朋友可以參考下

  最近在寫一個Javascript的架構,剛把DOMContentLoaded事件封裝好,略帶小興奮,把開發過程中遇到的原理和相容性問題做篇筆記,省的忘記到處找。

  我們在寫js代碼的時候,一般都會添加window.onload事件,主要是為了在DOM載入完後可以使用getElementById,getElementsByTagName等方法選取DOM元素進行操作,但是window.load會等到載入完DOM、指令碼、CSS,最後載入完圖片甚至是iframe中的所有資源才會觸發,很多時候網頁的圖片較多較大,要等最後圖片這個耗時大戶載入完才執行js明顯有些太遲了,很多時候都會影響使用者體驗。

  很多js架構都有個document.ready的功能,像JQuery的$(document).ready()方法,可以在DOM載入完就立即執行js代碼,讓圖片自個慢慢載入吧。

  document.ready的核心是DOMContentLoaded事件,firefox、chrome、opera、safari、ie9+都可以使用addEventListener(‘DOMContentLoaded',fn,false)進行事件綁定,而ie6~8不支援DOMContentLoaded事件,所以要針對ie6~8做相容性處理。

  資料上說ie6~8可以使用document.onreadystatechange事件監聽document.readyState狀態是否等於complete來判斷DOM是否載入完畢,如果頁面中嵌有iframe的話,ie6~8的document.readyState會等到iframe中的所有資源載入完才會變成complete,此時iframe變成了耗時大戶。但是經過測試,即使頁面中沒有iframe,當readyState等於complete時,實際觸發的是onload事件而不是DOMContentLoaded事件,對這點表示驚奇。

  還好ie有個特有的doScroll方法,當頁面DOM未載入完成時,調用doScroll方法時,就會報錯,反過來,只要一直間隔調用doScroll直到不報錯,那就表示頁面DOM載入完畢了,不管圖片和iframe中的內容是否載入完畢,此法都有效。

  如果有多個js檔案綁定了document.ready事件,為了防止瀏覽器重複綁定,同時有序執行,可以引入一個事件隊列機制來解決。

  以上就是document.ready事件的原理和相容性問題,下面貼段執行個體代碼,為了方便理解執行過程,使用函數封裝的模式,執行過程都寫在注釋裡了,如果有不妥之處歡迎指教。

//儲存domReady的事件隊列
eventQueue = [];

//判斷DOM是否載入完畢
isReady = false;

//判斷DOMReady是否綁定
isBind = false;

/*執行domReady()
 *
 *@param    {function}
 *@execute  將事件處理常式壓入事件隊列,並綁定DOMContentLoaded
 *          如果DOM載入已經完成,則立即執行
 *@caller
 */
function domReady(fn){
    if (isReady) {
        fn.call(window);
    }
    else{
        eventQueue.push(fn);
    };

    bindReady();
};

/*domReady事件綁定
 *
 *@param    null
 *@execute  現代瀏覽器通過addEvListener綁定DOMContentLoaded,包括ie9+
            ie6-8通過判斷doScroll判斷DOM是否載入完畢
 *@caller   domReady()
 */
function bindReady(){
    if (isReady) return;
    if (isBind) return;
    isBind = true;

    if (window.addEventListener) {
        document.addEventListener('DOMContentLoaded',execFn,false);
    }
    else if (window.attachEvent) {
        doScroll();
    };
};

/*doScroll判斷ie6-8的DOM是否載入完成
 *
 *@param    null
 *@execute  doScroll判斷DOM是否載入完成
 *@caller   bindReady()
 */
function doScroll(){
    try{
        document.documentElement.doScroll('left');
    }
    catch(error){
        return setTimeout(doScroll,20);
    };
    execFn();
};

/*執行事件隊列
 *
 *@param    null
 *@execute  迴圈執行隊列中的事件處理常式
 *@caller   bindReady()
 */
function execFn(){
    if (!isReady) {
        isReady = true;
        for (var i = 0; i < eventQueue.length; i++) {
            eventQueue[i].call(window);
        };
        eventQueue = [];
    };
};

//js檔案1
domReady(function(){
    ...
});
//js檔案2
domReady(function(){
    ...
});

//注意,如果是非同步載入的js就不要綁定domReady方法,不然函數不會執行,
//因為非同步載入的js下載之前,DOMContentLoaded已經觸發,addEventListener執行時已經監聽不到了

測試頁面:都載入了兩張很大的圖片,onload需要圖片載入完才能執行js,DOMContentLoaded只需等到DOM載入完即可執行js。可以開啟firebug查看載入過程,每次測試前記得先清理下瀏覽器緩衝。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.