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