學(xué)習(xí)要點(diǎn):
1.問題所在
2.設(shè)置代碼
處理頁面文檔加載的時(shí)候,我們遇到一個(gè)難題,就是使用 window.onload 這種將所有內(nèi)
容加載后(包括 DOM 文檔結(jié)構(gòu),外部腳本、樣式,圖片音樂等)這樣會導(dǎo)致在長時(shí)間加載
頁面的情況下,JS 程序是不可用的狀態(tài)。而 JS 其實(shí)只需要 HTML DOM 文檔結(jié)構(gòu)構(gòu)造完畢
之后就可以使用了,沒必要等待諸如圖片音樂和外部內(nèi)容加載。
一.問題所在
首先了解一下瀏覽器加載的順序:
1.HTML 解析完畢;
2.外部腳本和樣式加載完畢;
3.腳本在文檔內(nèi)解析并執(zhí)行;
4.HTML DOM 完全構(gòu)造起來;
5.圖片和外部內(nèi)容加載;
6.網(wǎng)頁完成加載。
PS:這里要了解一個(gè)問題,1-4 的加載是極快的,一剎那而已。而第 5 條,根據(jù)網(wǎng)速和
內(nèi)容的多少各有快慢,但總體上如果有圖片和外部內(nèi)容的話,比 1-4 條加起來都要慢很多。
PS:并且 JS 的 document.getElementById 這些只需要 1-4 條加載完畢后方可執(zhí)行,并不
需要加載第 5 條,所以,我們需要一種可以代替 window.onload 的更加快捷的加載方案。
二.設(shè)置代碼
非 IE 瀏覽器提供了一種加載事件:DOMContentLoaded 事件,這個(gè)事件可以在完成
HTML DOM 結(jié)構(gòu)之后就會觸發(fā),不會理會圖像音樂、JS 文件、CSS 文件或其他資源是否已
經(jīng)下載完畢。
目前支持 DOMContentLoaded 事件瀏覽器有:IE9+、Firefox、Chrome、Safari 3.1+和
Opera 9+都支持。
PS:臨時(shí)找的網(wǎng)上圖片的地址:
<img src="http://h.hiphotos.baidu.com/album/s%3D1600%3Bq%3D100/sign=0686e4a05982b2b7a39f3
dc2019df09e/d01373f082025aaf03cd026ffbedab64024f1a92.jpg" />
//傳統(tǒng)的加載方式
window.onload = function () { //等待網(wǎng)頁完全加載完畢
var box = document.getElementById('box');
alert(box.innerHTML);
};
//DOMContentLoaded 事件加載
if (document.addEventListener) { //DOM 結(jié)構(gòu)加載完畢
addEvent(document, 'DOMContentLoaded', function () {
var box = document.getElementById('box');
alert(box.innerHTML);
});
}
//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);
}
};
PS:這種方式創(chuàng)建空 script 標(biāo)簽,屬性擁有 defer,這個(gè)屬性就是定義需要加載完畢后
執(zhí)行,然后待 onreadystatechange 為 complete 時(shí),表示 DOM 結(jié)構(gòu)加載完畢了,再執(zhí)行。
在 IE 瀏覽器如果網(wǎng)頁上有<iframe>加載另一個(gè)網(wǎng)頁,我們發(fā)現(xiàn) IE 瀏覽器還需要加載完
畢 iframe 所有的內(nèi)容才可以執(zhí)行。而非 IE 瀏覽器的 DOMContentLoaded 事件則還是 DOM
加載完畢后就執(zhí)行了,在這里我們就發(fā)現(xiàn)IE 的這種方式并不完美,當(dāng)然,如果頁面沒有 iframe
的話就夠用了。
//使用 doScroll()來判斷 DOM 加載完畢
var timer = null;
timer = setInterval(function () {
try {
document.documentElement.doScroll('left');
var box = document.getElementById('box');
alert(box.innerHTML);
} catch (ex) {};
});
在 IE 中,任何 DOM 元素都有一個(gè) doScroll 方法,無論它們是否支持滾動條。為了判
斷 DOM 樹是否建成,我們只看看 documentElement 是否完整就是,因?yàn)?,它作為最外層?br>
元素,作為 DOM 樹的根部而存在,如果 documentElement 完整的話,就可以調(diào)用 doScroll
方法了。當(dāng)頁面一加載 JS 時(shí),我們就執(zhí)行此方法,當(dāng)然要 如果 documentElement 還不完整
就會報(bào)錯(cuò),我們在 catch 塊中重新調(diào)用它,一直到成功執(zhí)行,成功執(zhí)行時(shí)就可以調(diào)用 fn 方
法了
由此,我們可以結(jié)合一下上面兩種方案,做一個(gè)兼容的函數(shù)方便調(diào)用。
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);
});