http://school.cnd8.com/javascript/jiaocheng/76942.htm
由于
window.onload
事件需要在页面所有内容(包括图片等)加载完后,才执行,但往往我们更希望在DOM一加载完就执行脚本。其实在现在大部分主流浏览器上(Firefox3+,Opera9+,Safari3+,Chrome2+)都提供了这一事件方法:
addDOMLoadEvent
。
document.addEventListener("DOMContentLoaded",init,false);那对于IE我们如何模拟addDOMLoadEvent事件呢?
MatthiasMiller最早提供了如下的解决方案:
//forInternetExplorer(usingconditionalcomments)/*@cc_on@*//*@if(@_win32)document.write("<scriptid=__ie_onloaddefersrc=javascript:void(0)></script>");varscript=document.getElementById("__ie_onload");script.onreadystatechange=function(){if(this.readyState=="complete"){init();//calltheonloadhandler}};/*@end@*/而DiegoPerini在其后提供了一种利用
doScroll()
方法来模拟addDOMLoadEvent事件的方案,且现在主流的JavaScript框架(JQuery、YUI等)基本都采用的这一解决方案。
原理基本如下:
当ondocumentready事件触发,文档(document)已经完全解析和建立。如果组件需要操作最初的文档结构,初始化代码需被安置在这之后。ondocumentready事件告知组件,整个页面已被加载,且在初始文档的onload事件触发之前立即触发。
一些方法,例如doScroll,要求最初的文档被完全加载。如果这些方法是初始化函数的一部分,当ondocumentready事件触发,他们将被执行。
/***IEContentLoaded.js**Author:DiegoPerini(diego.periniatgmail.com)NWBOXS.r.l.*Summary:DOMContentLoadedemulationforIEbrowsers*Updated:05/10/2007*License:GPL/CC*Version:TBD**///@wwindowreference//@fnfunctionreferencefunctionIEContentLoaded(w,fn){vard=w.document,done=false,//onlyfireonceinit=function(){if(!done){done=true;fn();}};//pollingfornoerrors(function(){try{//throwserrorsuntilafterondocumentreadyd.documentElement.doScroll('left');}catch(e){setTimeout(arguments.callee,50);return;}//noerrors,fireinit();})();//tryingtoalwaysfirebeforeonloadd.onreadystatechange=function(){if(d.readyState=='complete'){d.onreadystatechange=null;init();}};}JQuery1.3.2中源码实现如下:
//IfIEandnotaniframe//continuallychecktoseeifthedocumentisreadyif(document.documentElement.doScroll&&window==window.top)(function(){if(jQuery.isReady)return;try{//IfIEisused,usethetrickbyDiegoPerini//http://javascript.nwbox.com/IEContentLoaded/document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}//andexecuteanywaitingfunctionsjQuery.ready();})();YUI2.7.0中源码实现如下:
if(EU.isIE){//ProcessonAvailable/onContentReadyitemswhenthe//DOMisready.YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);varn=document.createElement('p');EU._dri=setInterval(function(){try{//throwsanerrorifdocisnotreadyn.doScroll('left');clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}另外对于版本小于Safari3+的Safari浏览器,JohnResig也提供了一个解决方案:
if(/WebKit/i.test(navigator.userAgent)){//sniffvar_timer=setInterval(function(){if(/loaded|complete/.test(document.readyState)){clearInterval(_timer);init();//calltheonloadhandler}},10);}怿飞提示:
如果脚本是动态注入到页面上,则原生的DOMContentReady事件是不会被触发(即:IE除外)。
IE下对于在iframe里的使用addDOMLoadEvent事件,需做处理和慎用(这一点YUI做得不如JQuery细致)。
//formJQuery1.3.2//ensurefiringbeforeonload,maybelatebutsafealsoforiframesdocument.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);jQuery.ready();}});