DOM ready:
DOM ready(也称document ready),是一个被广泛用于代替window.onload的事件(准确的讲是一种状态)。对其不是很熟悉的朋友可以
看这里:比window.onload更好的方式(document ready)
在异步加载中的问题:
当一个绑定了DOM ready事件的脚本(绑定方式可参见:window.onload更好的方式(document ready) )采用异步的方式加载(相关链
接:异步加 载JS的五种方式(详解) )时,会发生这样的问题:脚本加载完成时,DOM ready事件已经触发过了,这就意味着这个脚本将不
会被执行。这个问题非常棘手,也很容易碰到,那么如何解决呢?你一定会想到,在脚本中加上这样的逻辑“如果DOM ready已经触发,那么
直接执行脚本,如果尚未触发,则向DOM ready事件绑定该脚本”。没错,这样一来这个问题就可以被解决了,但是还有新的问题,那就是如
何知道DOM ready事件已经触发了呢?jQuery则回避了这个问题,它采用了这种方式:做一个双重保险,如果DOM ready错过了那就退而使
用document.readyState == "complete"来作为脚本执行的时间起点。但这种方式显然大打折扣了(因为document.readyState ="complete"
的触发时间几乎和window.onload同时,当页面中有大量图片资源时问题就非常严重了。关于这些事件的触发时间对比,可见:window.onl -
-oad 更 好的方式(document ready) )。
更好的方法:
首先我们来分析一下各个浏览器的特性,在Firefox和Chrome中document.readyState值为interactive时DOM树就已经ready了,而IE不会出现
前面所讲的问题(因为我们是使用document.documentElement.doScroll来定时检测的),在Opera下document.readyState=="complete"和
DOM ready几乎是同时触发的(因此可以直接用document.readyState=="complete"来判断)。有了这些特性,这个问题就迎刃而解了(详
细请看下面的代码)。
Javascript代码:
(function(d, f){
if(window.attachEvent){
(function(){
try{
d.documentElement.doScroll("left");
}catch(err){
setTimeout(arguments.callee, 1);
return;
}
f();
})();
}else{
if((d.readyState == "interactive") && (!!alert) || (d.readyState == "complete")){
f();
}else{
function _f(){
d.removeEventListener("DOMContentLoaded", _f, false);
f();
}
d.addEventListener("DOMContentLoaded", _f, false);
}
}
})(document, main);
代码讲解:
1. 在Firefox和Chrome中,document.readyState=="interactive"时就已经DOM ready了。
2. 在IE中,在DOM ready之前调用document.documentElement.doScroll("left")都会报错,因此使用循环和try...catch来捕捉DOM ready。
3. 在Opera中,document.readyState=="interactive"时alert是不可访问的,因此!!alert将返回false。
4. main是我们所要向DOM ready绑定的函数。
注意事项:
document.readyState == "interactive" 是在DOMContentLoaded事件之前(会早几毫秒)触发的,不过在Chrome和Firefox中,这个时候确
实已经可以完全访问并操作(appendChild、removeChild)DOM元素了(即DOM tree已经ready)。
本文转自http://hi.baidu.com/flondon/item/247985275ba2833694f62b9a