当前位置: 首页 > 图文教程 > 网络编程 > Javascript > JS教程:addDOMLoadEvent事件

Javascript
编辑浪子版表单验证类
JavaScript脚本语言在网页中的简单应用
getElementById在任意一款浏览器中都可以用吗的疑问回复
“增强js程序代码的健壮性”之我见大量示例代码
javascript之卸载鼠标事件的代码
静态页面下用javascript操作ACCESS数据库(读增改删)的代码
javascript操作文本框readOnly
用javascript实现gb2312转utf-8的脚本
网站被黑的假象--ARP欺骗之页面中加入一段js
(JS实现)MapBar中坐标的加密和解密的脚本
几款极品的javascript压缩混淆工具
[原创]由亿起发(eqifa.com)的页面发现顶部的http://16a.us/8.js想到的js解密
JavaScript中的new的使用方法与注意事项
分别用两个函数实现的菜单
非常不错的模拟打字效果,目前仅支持纯文本、BR标签、和P标签
用javascript实现的支持lrc歌词的播放器
JS加ASP二级域名转向的代码
效果直逼flash的Div+Css+Js菜单
input之怎么清除默认值
用xhtml+css写的相册自适应 - 类似九宫格[兼容 ff ie6 ie7 opear ]

Javascript 中的 JS教程:addDOMLoadEvent事件


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 415 ::
收藏到网摘: n/a

由于 window.onload 事件需要在页面所有内容(包括图片等)加载完后,才执行,但往往我们更希望在 DOM 一加载完就执行脚本。其实在现在大部分主流浏览器上(Firefox 3+,Opera 9+,Safari 3+,Chrome 2+)都提供了这一事件方法:addDOMLoadEvent

document.addEventListener("DOMContentLoaded", init, false);

那对于 IE 我们如何模拟 addDOMLoadEvent 事件呢?

Matthias Miller 最早提供了如下的解决方案:

// for Internet Explorer (using conditional comments)
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
    if (this.readyState == "complete") {
        init(); // call the onload handler
    }
};
/*@end @*/

Diego Perini 在其后提供了一种利用 doScroll() 方法来模拟 addDOMLoadEvent 事件的方案,且现在主流的 JavaScript 框架(JQuery、YUI等)基本都采用的这一解决方案。

原理基本如下:

当 ondocumentready 事件触发,文档( document )已经完全解析和建立。如果组件需要操作最初的文档结构,初始化代码需被安置在这之后。ondocumentready 事件告知组件,整个页面已被加载,且在 初始文档的 onload 事件触发之前立即触发。

一些方法,例如 doScroll,要求最初的文档被完全加载。如果这些方法是初始化函数的一部分,当ondocumentready 事件触发,他们将被执行。

/*
 *
 * IEContentLoaded.js
 *
 * Author: Diego Perini (diego.perini at gmail.com) NWBOX S.r.l.
 * Summary: DOMContentLoaded emulation for IE browsers
 * Updated: 05/10/2007
 * License: GPL/CC
 * Version: TBD
 *
 */


// @w    window reference
// @fn    function reference
function IEContentLoaded (w, fn) {
   
var d = w.document, done = false,
   
// only fire once
    init
= function () {
       
if (!done) {
           
done = true;
            fn
();
       
}
   
};
   
// polling for no errors
   
(function () {
       
try {
           
// throws errors until after ondocumentready
            d
.documentElement.doScroll('left');
       
} catch (e) {
            setTimeout
(arguments.callee, 50);
           
return;
       
}
       
// no errors, fire
        init
();
   
})();
   
// trying to always fire before onload
    d
.onreadystatechange = function() {
       
if (d.readyState == 'complete') {
            d
.onreadystatechange = null;
            init
();
       
}
   
};
}

JQuery 1.3.2 中源码实现如下:

// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && window == window.top ) (function(){
   
if ( jQuery.isReady ) return;

   
try {
       
// If IE is used, use the trick by Diego Perini
       
// http://javascript.nwbox.com/IEContentLoaded/
        document
.documentElement.doScroll("left");
   
} catch( error ) {
        setTimeout
( arguments.callee, 0 );
       
return;
   
}

   
// and execute any waiting functions
    jQuery
.ready();
})();

YUI 2.7.0 中源码实现如下:

if (EU.isIE) {

   
// Process onAvailable/onContentReady items when the
   
// DOM is ready.
    YAHOO
.util.Event.onDOMReady(
            YAHOO
.util.Event._tryPreloadAttach,
            YAHOO
.util.Event, true);

   
var n = document.createElement('p');  

    EU
._dri = setInterval(function() {
       
try {
           
// throws an error if doc is not ready
            n
.doScroll('left');
            clearInterval
(EU._dri);
            EU
._dri = null;
            EU
._ready();
            n
= null;
       
} catch (ex) {
       
}
   
}, EU.POLL_INTERVAL);

}

另外对于版本小于 Safari 3+ 的 Safari 浏览器,John Resig 也提供了一个解决方案:

if (/WebKit/i.test(navigator.userAgent)) { // sniff
   
var _timer = setInterval(function() {
       
if (/loaded|complete/.test(document.readyState)) {
            clearInterval
(_timer);
            init
(); // call the onload handler
       
}
   
}, 10);
}

怿飞提示:

  1. 如果脚本是动态注入到页面上,则原生的 DOMContentReady 事件是不会被触发(即:IE 除外)。
  2. IE 下对于在 iframe 里的使用 addDOMLoadEvent 事件,需做处理和慎用(这一点 YUI 做得不如 JQuery 细致)。
    // form JQuery 1.3.2
    // ensure firing before onload, maybe late but safe also for iframes
    document
    .attachEvent("onreadystatechange", function(){
       
    if ( document.readyState === "complete" ) {
            document
    .detachEvent( "onreadystatechange", arguments.callee );
            jQuery
    .ready();
       
    }
    });

扩展阅读: