HTML DOM文檔加載是按順序執行的,這與瀏覽器的渲染方式有關係,一般瀏覽器渲染操作的順序如下:
第1步,解析HTML結構。
第2步,加載外部腳本和樣式表文件。
第3步,解析並執行腳本代碼。
第4步,構造HTML DOM模型。
第5步,加載圖片等外部文件。
第6步,頁面加載完畢。
例如,下面這個簡單的DOM文檔。
<html>
<head>
<title>網頁標題</title>
<style type="text/css">
body{font-size:12px;}
</style>
<link href="style.css"rel="stylesheet"type="text/css"media="all">
<script src="js.js"type="text/javascript"></script>
</head>
<body>
<p>
<script type="text/javascript">
function f1{}
</script>
<img src="1.gif"/>
</p>
<script type="text/javascript">
function f2{}
</script>
</body>
</html>
這個文檔的加載和構造順序如下,所謂構造就是把對應的標籤元素添加到DOM文檔對像模型中。
html→head→title→#text(網頁標題)→style→加載樣式→解析樣式→link→加載外部樣式表文件→解析外部樣式→script→加載外部腳本文件→解析外部腳本→執行外部腳本→body→p→script→加載腳本→解析腳本→執行腳本→img→script→加載腳本→解析腳本→執行腳本→加載外部圖像文件→頁面初始化完畢。
通過上面的HTML DOM加載順序,可以看到網頁頭部的腳本(由外部文件加載)會在構造HTML DOM文檔結構之前執行,這就會導致執行腳本無法訪問文檔結構模型。所以,一般可執行腳本都放在頁面初始化事件處理函數中,這樣能夠確保完全加載完文檔之後再執行腳本。
但是,如果頁面中包含很多外部文件,如大量圖片、視頻、音頻、動畫等文件,可能會延遲腳本的執行時間。為了避免JavaScript腳本處於較長時間的等待,可以把需要執行的腳本分塊放在HTML文檔結構中間,這樣只要在構造DOM後執行到腳本所在結構位置,就會執行腳本。
這種方法雖然能夠提前執行腳本,但是不能夠保證腳本可以訪問該位置後面的文檔結構,因為這些文檔結構還沒有被構造。不過,如果在頁面最後一個元素之前嵌入腳本,就可以最早執行腳本,並能夠確保腳本可以訪問HTML文檔結構模型中所有元素。例如:
<html>
<head>
<title></title>
</head>
<body>
<!--文檔結構-->
<script language="javascript"type="text/javascript">
//JavaScript執行腳本</script>
</body>
</html>
上述方法容易破壞文檔的結構,使整個文檔看起來很混亂,不利於管理。可以利用一種間接的方法來實現文檔結構的有序顯示,當加載完DOM文檔後,也意味著Document對象的屬性加載完畢,這樣可以判斷Document對象的幾個重要方法,如果存在,則說明DOM已經加載完畢,否則說明DOM還在加載中。通過這種方法既不影響文檔結構,又可以快速捕捉到DOM加載的過程,實現的代碼如下:
function f{
if(document&&document.getElementsByTagName&&document.getElementById&&document.body){
clearInterval(timer);
//JavaScript執行腳本
}
}
var timer=setInterval(f,10);
在函數f中,首先判斷Document對象的幾個重要方法是否已經加載完畢,如果加載完畢,則說明DOM結構已經完成加載,執行預定的JavaScript腳本。為了能夠實時跟蹤加載過程,這裡設計了一個定時器,不斷調用函數f,以便快速、準確地判斷DOM加載狀態。如果DOM加載完畢,則清除定時器,並開始執行腳本。