处理页面文档加载的时候,遇到一个难题,如果使用window.onload这种将所有内容加载后(包括DOM文档结构,外部脚本、样式,图片音乐等)这样会导致在长时间加载页面的情况下,JS程序是不可用的状态。而JS其实只需要HTML DOM文档结构构造完毕之后就可以使用,没有必要等到比如图片、音乐和外部内容加载才去执行。
传统DOM加载
window.onload = function(){
//执行的代码..
};
浏览器加载的顺序:
1.HTML解析完毕。
2.外部脚本和样式加载完毕。
3.脚本在文档内解析并执行。
4.HTML DOM树完全构造起来。
5.图片、音乐和外部内容加载。
6.网页完成加载。
这里需要了解一个问题:
1. 步骤1-4的加载是极快的,但是第5条,根据网速和内容的多少各有快慢。
2. 因此在步骤1-4完成之后,方可执行JS内部的程序。并不需要等到加载第5条完毕之后,所以需要提供一种可以替代window.onload更快的解决方案。
现代DOM加载
非IE浏览器:
if (document.addEventListener) {
addEvent(document, 'DOMContentLoaded', function () {
//执行的代码...
});
}
PS:非IE浏览器提供了一种加载事件:DOMContentLoaded,这个事件可以在完成HTML DOM结构之后就触发。不会理会图片、音乐和外部内容等是否已经下载完毕。
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') {
//执行的代码...
}
};
PS:在IE 浏览器如果网页上有<iframe>
加载另一个网页,我们发现IE 浏览器还需要加载完毕iframe 所有的内容才可以执行。而非IE 浏览器的DOMContentLoaded 事件则还是DOM加载完毕后就执行了,在这里我们就发现IE 的这种方式并不完美,当然,如果页面没有iframe的话就够用了。
IE浏览器方法二:
//使用doScroll()来判断DOM 加载完毕
var timer = null;
timer = setInterval(function () {
try {
document.documentElement.doScroll('left');
//执行的代码...
} catch (ex) {};
});
PS:在IE 中,任何DOM 元素都有一个doScroll 方法,无论它们是否支持滚动条。为了判断DOM 树是否建成,我们只看看documentElement 是否完整就是,因为,它作为最外层的元素,作为DOM 树的根部而存在,如果documentElement 完整的话,就可以调用doScroll方法了。当页面一加载JS 时,我们就执行此方法,当然要如果documentElement 还不完整就会报错,我们在catch 块中重新调用它,一直到成功执行,成功执行时就可以调用fn 方法了。
现代DOM加载兼容性:
function addDomLoaded(fn){
if(document.addEventListener){ //W3C
document.addEventListener('DOMContentLoaded',function(){
fn();
document.removeEventListener('DOMContentLoaded',arguments.callee,false); //arguments.callee
},false);
}else{
var timer = null;
timer = setInterval(function(){
try{
document.documentElement.doScroll('left');
fn();
}catch(ex){};
});
}
}
//调用
addDomLoaded(function(){
//执行的代码...
});