- Domready是每个lib都要实现的函数,因为dom还没有完全ready,那么对于对于dom元素的操作可能出错,因为dom树中可能还没有Load这个元素。为了保障不出现这样的错误,就出现地domready。对于每种浏览器Domready都有着自己不同的判断。
- Jquery的domready的实现和其它的lib的实现没有什么区别。
- //dom ready时执行 fn
- ready : function(fn) {
- bindReady();//注册监听
- if (jQuery.isReady)//ready就运行
- fn.call(document, jQuery);
- else
- // 增加这个函数到queue中。可见支持无数的ready的调用。
- jQuery.readyList.push(function() {
- return fn.call(this, jQuery);
- });
- return this;
- }
- 我们通过$(fn)的方法就是在调用这个方法。它首先通过bindReady()来注册监听dom是否已经loaded。如果已经loaded就运行fn。如果没有就把fn存放在readyList中。对于多个$(fn),把它们各自的fn参数保存在公共的jQuery. readyList的公共集合中。待到dom loaed之后统一运行。对于dom 已经loaded,就可以分别去运行fn。
- var readyBound = false;
- function bindReady() {
- if (readyBound)
- return;
- readyBound = true;
- // Mozilla, Opera, webkit nightlies 支持DOMContentLoaded事件
- if (document.addEventListener && !jQuery.browser.opera)
- //当DOMContentLoaded事件触发时就运行jQuery.ready
- document.addEventListener("DOMContentLoaded", jQuery.ready, false);
- //IE或不是frame的window
- if (jQuery.browser.msie && window == top)
- (function() {
- if (jQuery.isReady)
- return;
- try {
- // 在ondocumentready之前,一直都会抛出异常
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch (error) {
- //一直运行bindReady()(=arguments.callee)
- setTimeout(arguments.callee, 0);
- return;
- }
- jQuery.ready();//documentready就运行jQuery.ready
- })();
- if (jQuery.browser.opera)
- document.addEventListener("DOMContentLoaded", function() {
- if (jQuery.isReady)
- return;
- //只有styleSheets完全enable时,才是完全的load,其实还有pic
- for (var i = 0;i < document.styleSheets.length; i++)
- if (document.styleSheets[i].disabled) {//通过styleSheets来判断
- setTimeout(arguments.callee, 0);
- return;
- }
- jQuery.ready();
- }, false);
- if (jQuery.browser.safari) {
- var numStyles;
- (function() {
- if (jQuery.isReady)
- return;
- //首先得得到readyState=loaded或=complete
- if (document.readyState != "loaded"
- && document.readyState != "complete") {
- setTimeout(arguments.callee, 0);
- return;
- }
- //取得style的length,比较它们之间的长度,看看是不是完成loaded
- if (numStyles === undefined)
- numStyles = jQuery("style,
- link[rel=stylesheet]").length;
- if (document.styleSheets.length != numStyles) {
- setTimeout(arguments.callee, 0);
- return;
- }
- jQuery.ready();
- })();
- }
- //最后只能依赖于window.load.
- jQuery.event.add(window, "load", jQuery.ready);
- }
- 这段代码看起来很多,其实就是采用setTimeout(arguments.callee, 0);反复来运行bindReady。如果其得到dom ready的条件满足的话,就执行jQuery.ready()来执行通过$(fn)注册的fn函数。对于每种浏览器,这个满足的条件是不一样。上面的代码就是针对于几种常用的浏览器分别做了各自的处理。
- isReady : false,
- readyList : [],
- // Handle when the DOM is ready
- ready : function() {
- if (!jQuery.isReady) {
- jQuery.isReady = true;
- if (jQuery.readyList) {
- jQuery.each(jQuery.readyList, function() {
- this.call(document);
- });
- jQuery.readyList = null;
- }
- jQuery(document).triggerHandler("ready");
- }
- }
- });
- 当运行到jQuery.ready()的时候就说明dom已经完全的Loaded,那么现在就应该执行保存在jQuery.readyList中的fn。jQuery.ready()就是完成这个工作。