[置顶] jQuery乱谈(四)
jQuery核心函数除了最重要的jQuery()之外,还有jQuery.holdReady()、jQuery.sub()、jQuery.when()、jQuery.noConflict()。今天我就介绍一下这四个方法吧。
首先是jQuery.holdReady(),直接上代码:
holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; // readyWait就是一个计数器,表示还有多少个条目就绪事件才能执行
} else { jQuery.ready( true ); } }
使用方法如下:
jQuery.holdReady( hold )
作用:暂停或恢复.ready() 事件的执行
参数:hold为boolean值,指示是否暂停或恢复被请求的ready事件
jQuery.holdReady()方法允许jQuery的完成事件被该函数锁定。这个高级特性的典型应用场合是动态载入脚本,比如jQuery插件等。在附加的脚本载入完成前,即使页面已经准备好,jQuery的完成事件也不会被触发。这个函数必须在页面的靠前部分被调用,比如在标签当中,jQuery载入下一行。在完成事件被触发后调用此函数没有任何效果。使用方法:首先调用$.holdReady(true)[调用后完成事件将被锁定]。当准备好触发完成事件时,调用$.holdReady(false)。需要注意的是,可以对完成事件添加多个锁定,每个锁定对应一次$.holdReady(false)[解锁]调用。jQuery的完成事件将在所有的锁定都被解除,并且页面也已经准备好的情况下被触发。实际上就是为一些需要依赖动态脚本的代码加的一个安全锁,当所需要的动态脚本加载完毕后再执行就绪事件,而不是在DOM树构建成功后执行。
这里面又涉及到了jQuery.ready()方法:
ready: function( wait ) { // 如果还有等待的事件的话就取消执行,直接返回 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // 确定文档的body已经存在,延迟执行是为了防止IE"抽风" if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // isReady属性用来表示DOM树是否可用 jQuery.isReady = true; // 如果正常的ready事件触发, 减少等待的数目,然后继续等待 if ( wait !== true && --jQuery.readyWait > 0 ) { return; } readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger("ready").off("ready"); } }
请注意,这里的jQuery.ready()和jQuery(document).ready()是不一样的。
接着分析jQuery.sub()方法。该方法不接收参数,它的作用就是复制一份jQuery副本,并且不影响原来的jQuery对象:
jQuery.sub = function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; };
jQuery.sub这个方法主要用于两类特殊的情况,第一种情况是在不用污染jQuery对象原生方法的情况下提供一种干净的方式去覆盖扩展jQuery对象,另一种情况是帮助开发者封装和为jQuery插件构建一个命名空间。有了这个方法以后,就可以在混沌的jQuery插件世界里构建一个完全只属于自己的插件模块而不用担心自己模块会被污染或者自己的插件会和别的插件有冲突,但是同时也有几点需要注意,sub对象中所有的方法都指向原生的jQuery对象,也意味着事件的绑定和派发以及绑定在elments中的data项仍然需要经过全局的jQuery对象,此外还有ajax等。仔细看该方法的内部实现,很像缩小版的jQuery对象创建过程。它首先初始化一个新的function对象用于copy原生jQuery对象,接着借助原型链为sub对象copy原生对象的方法,再然后 产生新的document的上下文rootjQuerySub,最后在新的jQuerySub内部初始化方法中调用原生的init方法进行初始化,和jQuery原版对象的创建流程基本上一样!
还有俩,加油。jQuery.when()方法可接受一个或多个参数,该方法提供了一种方法来执行一个或多个参数延迟对象的回调函数,参数延迟对象通常表示异步事件:
when: function( subordinate /* , ..., subordinateN */ ) { var i = 0, resolveValues = core_slice.call( arguments ), length = resolveValues.length, // the count of uncompleted subordinates remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, // the master Deferred. If resolveValues consist of only a single Deferred, just use that. deferred = remaining === 1 ? subordinate : jQuery.Deferred(), // Update function for both resolve and progress values updateFunc = function( i, contexts, values ) { return function( value ) { contexts[ i ] = this; values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; if( values === progressValues ) { deferred.notifyWith( contexts, values ); } else if ( !( --remaining ) ) { deferred.resolveWith( contexts, values ); } }; }, progressValues, progressContexts, resolveContexts; // add listeners to Deferred subordinates; treat others as resolved if ( length > 1 ) { progressValues = new Array( length ); progressContexts = new Array( length ); resolveContexts = new Array( length ); for ( ; i < length; i++ ) { if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { resolveValues[ i ].promise() .done( updateFunc( i, resolveContexts, resolveValues ) ) .fail( deferred.reject ) .progress( updateFunc( i, progressContexts, progressValues ) ); } else { --remaining; } } } // if we're not waiting on anything, resolve the master if ( !remaining ) { deferred.resolveWith( resolveContexts, resolveValues ); } return deferred.promise(); }
这段代码我也看得似懂非懂,所以具体的分析我就不写了,如果你想深入了解的话参考:http://cmc3.cn/n/249.html和http://nuysoft.iteye.com/blog/1174798
最后一个方法,jQuery.noConflict(),用于解决命名冲突的问题。该方法接受一个可选的boolean参数,如果该参数=true,则将全局变量$和全局变量jQuery的控制权全部让出;如果没有参数或者该参数=false,则只将全局变量$的控制权让出。
注:如果将全局变量jQuery的控制权也让出,我们必须考虑到大多数插件依靠jQuery存在的变量,这种情况,可能不能正常操作。
noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }
代码就不解释了,是个人就能看懂,今天就写到这吧。