有時候我們只想在 dom 加載完成后運行 js ,而不是等所有圖片加載完成。所以不需要 onload , onload 會加載圖片等其他媒體。很消耗時間。
原:http://blog.csdn.net/shoushou71/article/details/52252340
前沿
處理頁面文檔加載的時候,我們遇到一個難題,就是使用window.onload這種將所有內容加載后(包括DOM文檔結構,外部腳本、樣式,圖片音樂等)這樣會導致在長時間加載頁面的情況下,js程序是不可用的狀態。而JS其實只需要HTML DOM文檔結構構造完畢之后就可以使用了,沒必要等待諸如圖片音樂和外部內容加載。
一.問題所在
首先了解一下瀏覽器加載的順序:
1.HTML解析完畢;
2.外部腳本和樣式加載完畢;
3.腳本在文檔內解析並執行;
4.HTML DOM完全構造起來;
5.圖片和外部內容加載;
6.網頁完成加載。
PS:這里要了解一個問題,1-4的加載是極快的,一剎那而已。而第5條,根據網速和內容的多少各有快慢,但總體上如果有圖片和外部內容的話,比1-4條加起來都要慢很多。
PS:並且JS的document.getElementById這些只需要1-4條加載完畢后方可執行,並不需要加載第5條,所以,我們需要一種可以代替window.onload的更加快捷的加載方案。
前台測試代碼:
``` html
<body>
<div id="box">box</div>
<img
src="http://h.hiphotos.baidu.com/album/s%3D1600%3Bq%3D100/sign=0686e4a05982b2b7a39f3
dc2019df09e/d01373f082025aaf03cd026ffbedab64024f1a92.jpg"></img
</body>
```
``` js
//傳統的DOM加載
window.onload = function () {
var box = document.getElementById('box');
alert(box.innerHTML);
};
```
//PS:如果有圖片,那么圖片加載完畢后,方可執行onload里面的內容
二、解決方案
非IE瀏覽器提供了一種加載事件:DOMContentLoaded事件,這個事件可以在完成HTML DOM結構之后就會觸發,不會理會圖像音樂、JS文件、CSS文件或其他資源是否已經下載完畢。
目前支持DOMContentLoaded事件瀏覽器有:IE9+、Firefox、Chrome、Safari 3.1+和Opera 9+都支持。
``` html
//DOMContentLoaded事件加載
if (document.addEventListener) { //DOM結構加載完畢
addEvent(document, 'DOMContentLoaded', function () {
var box = document.getElementById('box');
alert(box.innerHTML);
});
}
<span style="font-size:14px;color:#333333;"><span style="font-family:宋體;">//PS:如果有圖片,先執行節點操作的內容,然后再緩緩加載圖片,也就是說,當DOM樹結構加載完畢后即可執行了</span></span>
<span style="font-size:14px;color:#333333;"><span style="font-family:宋體;"></span></span>
```
IE不支持DOMContentLoaded事件,可以采用方式:創建空script標簽,屬性擁有defer,這個屬性就是定義需要加載完畢后執行,然后待onreadystatechange為complete時,表示DOM結構加載完畢了,再執行。
``` html
//IE瀏覽器加載
document.write("<script id=\"ie_onload\" defer=\"defer\" src=\"javascript:void(0)\">
<\/script>");
var script = document.getElementById("ie_onload");
script.onreadystatechange = function () {
if (this.readyState=='complete') {
var box = document.getElementById('box');
alert(box.innerHTML);
}
};
```
另外,在IE瀏覽器如果網頁上有<iframe>加載另一個網頁,我們發現IE瀏覽器還需要加載完畢iframe所有的內容才可以執行。而非IE瀏覽器的DOMContentLoaded事件則還是DOM加載完畢后就執行了,在這里我們就發現IE的這種方式並不完美,當然,如果頁面沒有iframe的話就夠用了。
在IE中,任何DOM元素都有一個doScroll 方法,無論它們是否支持滾動條。為了判斷DOM樹是否建成,我們只看看documentElement是否完整就是,因為,它作為最外層的元素,作為 DOM樹的根部而存在,如果documentElement完整的話,就可以調用doScroll方法了。當頁面一加載JS時,我們就執行此方法,當然要 如果documentElement還不完整就會報錯,我們在catch塊中重新調用它,一直到成功執行,成功執行時就可以調用 fn方法了
``` js
//使用doScroll()來判斷DOM加載完畢
var timer = null;
timer = setInterval(function () {
try {
document.documentElement.doScroll('left');
var box = document.getElementById('box');
alert(box.innerHTML);
} catch (ex) {};
});
```
由此,我們可以結合一下上面兩種方案,做一個兼容的函數方便調用。
``` js
function addDomLoaded(fn) {
if (document.addEventListener) { //W3C
addEvent(document, 'DOMContentLoaded', function () {
fn();
removeEvent(document, 'DOMContentLoaded', arguments.callee);
});
}
else { //IE
var timer = null;
timer = setInterval(function () {
try {
document.documentElement.doScroll('left');
fn();
} catch (ex) {};
});
}
}
addDomLoaded(function () {
var box = document.getElementById('box');
alert(box.innerHTML);
});
//PS:有效,DOM加載完畢后執行了節點操作,並且后面才加載完畢圖片
```
三、總結:
雖然以上對於主流瀏覽器和主流瀏覽器的版本已經非常夠用了,但還有幾個小細節我們需要了解一下。Opera8之前不支持,webkit引擎瀏覽器525之前不支持,Firefox2有嚴重bug。
對於非IE,又不支持DOMContentLoaded,可以直接用傳統的window.onload來執行,因為目前來說這種瀏覽器基本滅絕了,也可以document.readyState輪詢,直到完畢。
