dom ready的学习

思路:1.调用dom.ready时,先判断下dom是否ready了,如果dom已经ready,则直接执行函数,否则,推入readyList数组等待执行。

 

          2.判断domready,标准浏览器下,有document.DOMContentLoaded事件表明domready,而IE下,则通过doScroll来模拟,原理是在IE中,任何DOM元素都有一个doScroll 方法。当documentElement可以调用doScroll时,证明dom加载完成了。

          判断domready的原理如上,但在实际应用中,我看到很多代码都是在进行上面的判断前,先判断document.readyState === 'complete',在正美的http://www.cnblogs.com/rubylouvre/archive/2009/12/30/1635645.html这篇文章里,有列举了文档的加载顺序,列举的第3点不知能否解释上面的疑问,但我印象中好像readyState都是要在onreadystatechange里判断的。在下面的IE判断分支里,则有绑定了document的onreadystatechange事件进行判断。还有个疑问是在很多代码中,看到在执行doScroll时,先判断下是不是在iframe中,不是才调用。我想可能是因为执行到iframe里面时,dom应该都是加载完成的了吧,所以如果是在iframe中的话,就没有必要在进行doScroll判断了,纯属猜测。

 

var dom = {
        isReady: false,  //用于标识dom加载是否完成
        readyList: [],   //用于存放dom ready要执行的函数
        
        //用于当dom ready时,调用此函数依次执行存放在readyList里的函数
        fireReady: function(){
            if(this.isReady) return;
            this.isReady = true;

            if(this.readyList){
                var i = 0,readyFn;
                while(readyFn = this.readyList[i++]){
                    readyFn();
                }
                this.readyList.length = 0;  //执行到这里时,readyList数组则可以回收了,有人用this.readyList = undefined,也有人将this.readyList.length = 0,以标识此数组可回收。具体是怎样,我其实不知道,这里我选择将length清空的做法。
            }
        },
        ready: function(fn){
            if(this.isReady){
                return fn();   //这里,既然dom已经ready了,下面的代码就不需要执行了。所以直接执行函数并返回。
            }else{
                this.readyList.push(fn);
            }

            //不明白
            if(document.readyState === 'complete'){
                return this.fireReady();
            }

            if(document.addEventListener){  //标准浏览器
                document.addEventListener('DOMContentLoaded',function(){
                    document.removeEventListener('DOMContentLoaded',arguments.callee,false);
                    dom.fireReady();
                },false)
            }else{    //IE
                document.attachEvent('onreadystatechange',function(){
                    document.detachEvent('onreadystatechange',arguments.callee);
                    dom.fireReady();
                });

                (function(){
                    try{
                        document.documentElement.doScroll('left');
                    }catch(e){
                        setTimeout(arguments.callee,4);
                        return;
                    }
                    dom.fireReady();
                })();
            }

        }
    };

        

    dom.ready(function(){
        alert('domready1')
    })
    dom.ready(function(){
        alert('domready2')
    })

    
setTimeout(function(){
    dom.ready(function(){
        alert('延迟2秒,测试domready后的执行');
    });
}, 2000);

  

测试代码:

 

参考文章或代码:

http://www.cnblogs.com/rubylouvre/archive/2009/08/26/1554204.html 

http://www.cnblogs.com/rubylouvre/archive/2009/12/30/1635645.html 

http://www.cnblogs.com/rubylouvre/archive/2010/04/15/1712780.html 

https://github.com/chenmnkken/easyjs

posted @ 2012-10-01 17:34  肥杜  阅读(485)  评论(0编辑  收藏  举报