JavaScript 判斷 DOM 何時加載完畢


處理HTML DOM文檔存在一個難題是,JavaScript可以在DOM完全加載之前執行,這會給你的代碼引發不少的潛在問題。瀏覽器的渲染和操作順序大致如下列表:

  • HTML解析完畢
  • 外部腳本和樣式表加載完畢
  • 腳本在文檔內解析並執行
  • HTML DOM完全構造起來
  • 圖片和外部內容加載
  • 網頁完成加載

 

在網頁頭部並且從外部文件加載的腳本會在HTML真正構造之前執行。如前所述,這是個至關重要的問題,因為這兩處執行的腳本並不能訪問還不存在的DOM。幸好,我們還有若干的補救方法。

 

目前,最常用的級數是完全等待整個頁面加載完畢才執行DOM操作。這種技術只需利用window對象的load事件來綁定一個函數,頁面加載完畢即可觸發。

 

addEvent(window, "load", function(){
    // do something
});


最簡單的操作卻是最慢的。在加載過程的順序列表中,你會注意到頁面的加載完畢與否完全被最后一步所掌控。這就是說,如果頁面有很多的圖片、視頻等,用戶可能得登上一段時間JavaScript才執行。

另一種級數可用以監聽 DOM 加載狀態,可能是最復雜的(從實現角度來看),但也是最有效地。

這項技術在不堵塞瀏覽器加載的情況下盡可能快地檢查 HTML DOM文檔是否已經加載了執行所必須得屬性。以下是檢查HTML DOM是否可用的幾個要點:

  1. document: 你需要知道DOM文檔是否已經加載。若能足夠快地檢查,運氣好的話你會看到undefined。
  2. document.getElementsByTagName和document.getElementById:頻繁使用document.getElementsByTagName和document.getElementById函數檢查文檔,當存在這些函數則表明DOM已經加載完畢。
  3. document.body: 作為額外補充,檢查元素是否已經完全加載。理論上前一個檢查應該已經能做出判斷,但我發現有些情況下還是不夠。

使用這些檢查就足夠判斷DOM是否可用了(“足夠”在此表示可能會有一定毫秒級的時間差)。這個方法幾乎沒有瑕疵。單獨使用前述檢查,腳本應該可以在現代瀏覽器中運行得相對良好。但是,最近(2008年?)Firefox實現了緩存改進,使得window加載事件實際上可以在腳本能檢查到DOM是否可用之前觸發。為了能發揮這個優勢,我同時為window加載事件附加檢查,以期能獲得更快的執行速度。


最后,domReady函數集合了所有需要在DOM可用時就執行的函數的引用。一旦DOM被認為是可用的,就調用這些引用並按順序一一執行。

// 監聽 DOM 是否可用的函數
function domReady(f) {
    // 假如DOM已經加載,馬山執行函數
    if(domReady.done) return f();

    // 假如我們已經增加了一個函數
    if(domReady.timer) {
        // 把它假如待執行函數清單中
        domReady.ready.push(f);
    } else {
        // 為頁面加載完畢綁定一個事件,以防它最先完成。
        addEvent(window, "load", isDOMReady);
        // 初始化執行函數的數組
        domReady.ready = [f];
        // 盡可能快的檢查DOM是否已可用
        domReady.timer = setInterval(isDOMReady, 13);
    }
}

// 檢查 DOM 是否已可操作
function isDOMReady() {
    // 如果我們能判斷出DOM已可能,忽略
    if(domReady.done) return false;

    // 檢查若干函數和元素是否可能
    if(document && document.getElementsByTagName && document.getElementById && document.body) {
        // 如果可用,我們停止檢查
        clearInterval(domReady.timer);
        domReady.timer = null;

        // 執行所有正在等待的函數
        for(var i = 0; i < domReady.ready.length; i++) {
            domReady.ready[i]();
            // 記錄我們在此已經完成
            domReady.ready = null;
            domReady.done = true;
        }
    }
}

 

現在我們來看看在HTML文檔中是如何執行的。假設已經將domReady函數寫到一個名為domready.js的外部文件中

<html>
    <head>
        <title> Testing DOM Loading</title>
        <script src="domready.js"></script>
        <script>
            domReady(function(){
                alert("The DOM is loaded!");
                // do something
            });
        </script>
    </head>
    <body>
        <h1>Testing DOM Loading</h1>
        <!-- 這里是大量的HTML -->
    </body>
</html>

 內容摘自《精通JavaScript》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM