onload 和 DOMContentLoaded 的陷阱
在正常情况下:
- window.onload 事件在所有页面元素(包括图片,脚本等)都下载完毕后才会触发。
- 除了 IE,其它浏览器支持 DOMContentLoaded 事件。当 DOM 内容下载完毕,就会立刻触发。
- 事件处理器必须在事件触发前注册才有效,否则不会被执行。例子:在 window 已经 load 完成后,再给 window.onload 注册的处理器不会被执行。
- 针对 IE,有各种模拟 DOMContentLoaded 事件的办法。目前被广泛采纳的方案是判断 document 是否可以滚动(doScroll)。一旦可以滚动,就意味着 DOM Content 已经加载完毕。
下面说两个陷阱:
- 在 setTimeout 里给 window.onload 添加处理器。这是不可靠的,无法保证添加的处理器一定会执行。是否执行取决于 setTimeout 的延时和页面内容的加载时间。比如:
// Test 1. 在 onload 后添加 onload handler setTimeout(function() { onLoad(function() { alert('Test 1: window loaded.'); // 不一定执行 }); }, 20); - 在动态加载的 script 的 onload 事件里,给 window.DOMContentLoaded 添加处理器。这更不可靠,除了 IE,其它浏览器下根本不会执行。比如:
// Test 2. 测试动态添加 script getScript('http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js', function() { alert('Test 2: jQuery loaded.'); onReady(function() { alert('Test 2: content loaded.'); }); // 不可靠 });
测试页面:load_test.html
最后提一点:从上面的测试页面中可以看出,IE 下模拟 DOMContentLoaded 事件仅仅是模拟,和其它浏览器依旧存在本质上的差异。在 IE 真正原生支持 DOMContentLoaded 前,疯狂使用$(document).ready(...), YAHOO.util.Event.onDOMReady(...)等方法时,依旧需要谨慎,要留意陷阱。

July 3rd, 2009 on 16:41
沙发,好文章
July 3rd, 2009 on 17:38
错别字:标题+正文都有。“陷进”
July 3rd, 2009 on 18:55
的确safari 4刷新后会崩溃
July 3rd, 2009 on 19:47
是不是说jqury的ready是dom结构就绪就触发的…
July 3rd, 2009 on 21:51
好文要收藏。
不过有个小疑问,貌似 jQuery 的 ready 在 IE 下的实现是通过 元素的 defer 属性?
July 4th, 2009 on 22:32
@birdstudio: jQuery的ready也是用的doScroll
July 5th, 2009 on 18:07
jq用的doscroll哈
July 9th, 2009 on 9:39
ie 下面script defer 很好用啊
safari 下面只能设置定时检查了。
May 10th, 2010 on 13:20
不错的文章!赞!
leave a reply