js实现domready问题

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的几种状态是这样的

clipboard.png

这样不就变成load事件了吗?

阅读 2.9k
1 个回答

当文档和所有设置了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实现的思路

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题