Posted in Javascript onDecember 06, 2009
dom加载完后执行,一直不了解,基于对网上的一些方法逻辑不了解,所以去看了《jquery源代码研究(ready函数) 》这篇文章后自己写入如下代码(已有详细说明)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>document.ready</title> <script type="text/javascript" src="js/jquery-1.3.2.js"></script> <script type="text/javascript"> var Darren; (function(){ var isReady=false; //是否已经加载完毕 var readBound=false; //判断是否已经调用过循环事件 var readylist=[]; //把需要执行的方法先暂存在这个数组里 //判断浏览器,该方法来自Cloudgamer JavaScript Library v0.1 var Browser = (function(ua){ var b = { msie: /msie/.test(ua) && !/opera/.test(ua), opera: /opera/.test(ua), safari: /webkit/.test(ua) && !/chrome/.test(ua), firefox: /firefox/.test(ua), chrome: /chrome/.test(ua) }; var vMark = ""; for (var i in b) { if (b[i]) { vMark = i; } } if (b.safari) { vMark = "version"; } b.version = RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0"; b.ie = b.msie; b.ie6 = b.msie && parseInt(b.version) == 6; b.ie7 = b.msie && parseInt(b.version) == 7; b.ie8 = b.msie && parseInt(b.version) == 8; return b; })(window.navigator.userAgent.toLowerCase()); function bindReady() { if(readBound){ //保证bindReady方法只执行一遍 return; } readBound=true; //For IE并且不是嵌套在frame中 if (Browser.msie && window==top) { (function(){ if (isReady) { return; } try { document.documentElement.doScroll("left"); //如果没加载dom完毕这个会报错 } catch (error) { setTimeout(arguments.callee, 0); //循环调用父函数,也就是ready方法 return; } Test.Done(); })(); }else if(Browser.firefox)//For FF { document.addEventListener( "DOMContentLoaded", Test.Done, false ); } } var Test={ ready:function(fn){ bindReady();//判断是否加载完毕 if(isReady) { fn.call(document); //加载完毕,直接调用 }else{ readylist.push(fn);//如果还没加载完成则将该方法暂存到readylist数组中,以便以后调用 } return this; } }; //静态方法:加载完毕执行 Test.Done=function(){ if (!isReady) { isReady=true; } readylist[0].call(document); } Darren=Test; })(); //测试 Darren.ready(function(){ alert("my"); document.getElementById("test").innerHTML="haha" //成功读取dom }); $(function(){alert("jq")}); window.onload=function(){alert("default")} </script> </head> <body> <div id="test">test</div> </body> </html>
由于要和jq做对比,所以测试时候需要导入jq库。函数本身是没有调用jq的,请放心引用。
代码我通过封装完成,直接Darren.ready(fn)就可执行。
后来通过测试还是出现一个奇怪的问题:在FF下的执行顺序是jq -> my -> load 。也就是说我这个函数能够在onload事件执行前触发,但会晚于jq的ready。对这个还是比较满意。
但是在IE下测试居然是:jq -> load -> my。也就是 我的这个函数虽然能够把代码提前,但是还是在onload事件执行后触发的,百思不得其解。
完同志们解答下如何实现onload之前执行,jq又是怎么实现的,我完全模拟jq的结构,但是还是不能达到目的,难道中间有漏?
另大家可以参考下面的代码
var ready=function(readyCall) { if(document.addEventListener) document.addEventListener("DOMContentLoaded",function() { document.removeEventListener("DOMContentLoaded",arguments.callee,false); readyCall(); },false); else if(document.attachEvent) {//for IE if(document.documentElement.doScroll && window.self==window.top) { (function() { try { document.documentElement.doScroll("left"); }catch(ex) { setTimeout(arguments.callee,5); return; } readyCall(); })(); }else {//maybe late but also for iframes document.attachEvent("onreadystatechange",function() { if(document.readyState==="complete") { document.detachEvent("onreadystatechange", arguments.callee); readyCall(); } }); } } }
javascript 模拟JQuery的Ready方法实现并出现的问题
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@