jquery之 domready分析(转载)
其他JS框架的domrady实现
http://www.jb51.net/article/26251.htm
1 Domready是每个lib都要实现的函数,因为dom还没有完全ready,那么对于对于dom元素的操作可能出错,因为dom树中可能还没有Load这个元素。为了保障不出现这样的错误,就出现地domready。对于每种浏览器Domready都有着自己不同的判断。 2 Jquery的domready的实现和其它的lib的实现没有什么区别。 3 //dom ready时执行 fn 4 ready : function(fn) { 5 bindReady();//注册监听 6 if (jQuery.isReady)//ready就运行 7 fn.call(document, jQuery); 8 else 9 // 增加这个函数到queue中。可见支持无数的ready的调用。 10 jQuery.readyList.push(function() { 11 return fn.call(this, jQuery); 12 }); 13 return this; 14 } 15 我们通过$(fn)的方法就是在调用这个方法。它首先通过bindReady()来注册监听dom是否已经loaded。如果已经loaded就运行fn。如果没有就把fn存放在readyList中。对于多个$(fn),把它们各自的fn参数保存在公共的jQuery. readyList的公共集合中。待到dom loaed之后统一运行。对于dom 已经loaded,就可以分别去运行fn。 16 var readyBound = false; 17 18 function bindReady() { 19 if (readyBound) 20 return; 21 readyBound = true; 22 23 // Mozilla, Opera, webkit nightlies 支持DOMContentLoaded事件 24 if (document.addEventListener && !jQuery.browser.opera) 25 //当DOMContentLoaded事件触发时就运行jQuery.ready 26 document.addEventListener("DOMContentLoaded", jQuery.ready, false); 27 28 //IE或不是frame的window 29 if (jQuery.browser.msie && window == top) 30 (function() { 31 if (jQuery.isReady) 32 return; 33 try { 34 // 在ondocumentready之前,一直都会抛出异常 35 // http://javascript.nwbox.com/IEContentLoaded/ 36 document.documentElement.doScroll("left"); 37 } catch (error) { 38 //一直运行bindReady()(=arguments.callee) 39 setTimeout(arguments.callee, 0); 40 return; 41 } 42 jQuery.ready();//documentready就运行jQuery.ready 43 })(); 44 45 if (jQuery.browser.opera) 46 document.addEventListener("DOMContentLoaded", function() { 47 if (jQuery.isReady) 48 return; 49 //只有styleSheets完全enable时,才是完全的load,其实还有pic 50 for (var i = 0;i < document.styleSheets.length; i++) 51 if (document.styleSheets[i].disabled) {//通过styleSheets来判断 52 setTimeout(arguments.callee, 0); 53 return; 54 } 55 jQuery.ready(); 56 }, false); 57 58 if (jQuery.browser.safari) { 59 var numStyles; 60 (function() { 61 if (jQuery.isReady) 62 return; 63 //首先得得到readyState=loaded或=complete 64 if (document.readyState != "loaded" 65 && document.readyState != "complete") { 66 setTimeout(arguments.callee, 0); 67 return; 68 } 69 //取得style的length,比较它们之间的长度,看看是不是完成loaded 70 if (numStyles === undefined) 71 numStyles = jQuery("style, 72 link[rel=stylesheet]").length; 73 if (document.styleSheets.length != numStyles) { 74 setTimeout(arguments.callee, 0); 75 return; 76 } 77 jQuery.ready(); 78 })(); 79 } 80 81 //最后只能依赖于window.load. 82 jQuery.event.add(window, "load", jQuery.ready); 83 } 84 这段代码看起来很多,其实就是采用setTimeout(arguments.callee, 0);反复来运行bindReady。如果其得到dom ready的条件满足的话,就执行jQuery.ready()来执行通过$(fn)注册的fn函数。对于每种浏览器,这个满足的条件是不一样。上面的代码就是针对于几种常用的浏览器分别做了各自的处理。 85 isReady : false, 86 readyList : [], 87 // Handle when the DOM is ready 88 ready : function() { 89 if (!jQuery.isReady) { 90 jQuery.isReady = true; 91 if (jQuery.readyList) { 92 jQuery.each(jQuery.readyList, function() { 93 this.call(document); 94 }); 95 jQuery.readyList = null; 96 } 97 jQuery(document).triggerHandler("ready"); 98 } 99 } 100 }); 101 当运行到jQuery.ready()的时候就说明dom已经完全的Loaded,那么现在就应该执行保存在jQuery.readyList中的fn。jQuery.ready()就是完成这个工作。