function myDOMReady(fn){
//判断如果支持addEc=ventListener(非IE--IE支持的是attachEvent)则绑定DOMContentLoaded事件
if(document.addEventListener){
document.addEventListener("DOMContentLoaded",fn,false);
}else{
IEContenLoaded(fn);
}
//IE下模拟DOMContentLoaded
function IEContenLoaded(fn){
var done = false;
//只执行一次用户的回调函数init
var init = function(){
if(!done){
done = true;
fn();
}
}
(function(){
try{
//DOM树未创建完之前调用doScroll会抛出错误
window.document.documentElement.doScroll("left");
}catch(error){
//延迟再执行,arguments.callee调用自己
setTimeout(argument.callee,1);
return;
}
//没有错误表示DOM树创建完毕,执行用户回调
init();
})();
//监听document的加载状态
window.document.onreadystatechange = function(){
//如果用户是在DOMReady之后调用的函数立即执行用户回调
if(window.document.readyState == 'complete'){
window.document.onreadystatechange=null;
init();
}
}
}
}
IE的实现中,为什么最后判断状态是complete,但是我在mdn上查关于Document.readyState的几种状态是这样的
这样不就变成load事件了吗?
当文档和所有设置了
defer
属性的延迟脚本都加载完毕时,浏览器会触发Document对象上的DOMContentLoaded
事件,并且标志着你可以操作页面上的DOM元素。但是该事件并非DOM标准事件,而是HTML5规范中标准化的,所以对于不支持的浏览器需要使用onreadystatechange
事件来模拟,当readyState
属性值变为complete
时,说明此时所有资源,无论是文档,异步脚本,同步脚本还是图片都已经加载完毕,所以会触发Window对象的load
事件。因此,你会发现其实
onreadystatechange
事件是发生在DOMContentLoaded
事件之后,在load
事件之前的。之后,Diego Perini发现了对于IE浏览器来说,通过
document.documentElement.doScroll("left")
来判断DOM树是否构建完毕,这比监听onreadystatechange
事件更接近于DOMContentLoaded
。这样解释应该好懂一些吧。
参考链接:主流框架中DOMReady实现的思路