jQuery.API源码深入剖析以及应用实现(2) - jQuery对象访问和数据缓存
2010-09-14 13:40:09 来源:WEB开发网前言
上篇主要介绍JQuery的核心函数的原理机制,这篇将开始介绍jQuery对象访问和数据缓存原理,主要内容包括:
分析
一、jQuery对象访问
1. 【each(callback)】
例子:
HTML代码 | jQuery代码 | 运行结果 |
<img/><img/> |
| [ <img src=http://tech.ddvip.com/2009-02/"test0.jpg" />, <img src=http://tech.ddvip.com/2009-02/"test1.jpg" /> ] |
<img/><img/> |
| 切换样式example |
现在来看each方法的具体实现如下:
jQuery.fn=jQuery.prototype={
each:function(callback,args){
returnjQuery.each(this,callback,args);
}
}
可以看到它返回的是全局的each方法,并且将自身jQuery对象做为参数给它,全局的each方法的具体实现如下:
//args作为内部成员的调用来使用
each:function(object,callback,args){
varname,i=0,length=object.length; //当object为jQuery对象时,length非空
if(args){
if(length===undefined){
for(nameinobject)
if(callback.apply(object[name],args)===false)
break;
}else
for(;i<length;)
if(callback.apply(object[i++],args)===false)
break;
//以下是客户端程序进行调用
}else{
if(length===undefined){
for(nameinobject)
if(callback.call(object[name],name,object[name])===false)
break;
}else
for(varvalue=object[0];
i<length&&callback.call(value,i,value)!==false;value=object[++i]){}
}
returnobject;
}
现在我们关注下 for ( var value = object[0];i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 这句代码;
其中object[0]取得jQuery对象中的第一个DOM元素,通过for循环,得到遍历整个jQuery对象中对应的每个DOM元素,通过callback.call( value,i,value); 将callback的this对象指向value对象,并且传递两个参数,i表示索引值,value表示DOM元素;其中callback是类似于 function(index, elem) { ... } 的方法。所以就得到 $("...").each(function(index, elem){ ... });
2. 【size()】和【length】
这两个都是得到jQuery 对象中元素的个数,具体实现如下:
size:function(){
returnthis.length;
}
3. 【selector】和【context】
selector返回传给jQuery()的原始选择器。
context返回传给jQuery()的原始的DOM节点内容,即jQuery()的第二个参数。如果没有指定,那么context指向当前的文档(document)。
这两个属性在上一篇文章也有提及,请参考jQuery.API源码深入剖析以及应用实现(2) - 对象访问和数据缓存,这里不再敖述。
4. 【get()】和【get(index)】
get()取得所有匹配的 DOM 元素集合。
get(index)取得其中一个匹配的DOM元素,index表示取得第几个匹配的元素。
$(this).get(0)与$(this)[0]等价。
现在看下get方法的具体实现如下:
get:function(num){
returnnum===undefined?
//当num为undefined时,返回所有匹配的DOM元素集合
jQuery.makeArray(this):
//当num不为undefined时,返回第num+1个匹配的DOM元素
this[num];
}
当不包含num时,调用jQuery.makeArray方法,具体实现如下:
makeArray:function(array){
varret=[];
if(array!=null){
vari=array.length;
//Thewindow,strings(andfunctions)alsohave'length'
if(i==null||typeofarray==="string"||jQuery.isFunction(array)||array.setInterval)
ret[0]=array;
else
while(i)
ret[--i]=array[i];
}
returnret;
}
可以看出这里的array为jQuery对象,因此执行 while( i ) ret[--i] = array[i];, 返回的是以array所有匹配的DOM元素所组成的数组。这和前面的定义相一致。
当包含num时,直接返回 this[ num ],所以这样验证了 $(this).get(0)与$(this)[0]等价 的说明。
5. 【index(subject)】
搜索与参数表示的对象匹配的元素,并返回相应元素的索引值。
例子
HTML代码 | jQuery代码 |
<div id="foobar"><div></div><div id="foo"></div></div> |
|
现在看下index方法的具体实现如下:
index:function(elem){
returnjQuery.inArray(
//如果elem为一个jQuery对象,那么得到的是第一个匹配的DOM元素
elem&&elem.jquery?elem[0]:elem
,this);
}
继续查看jQuery.inArray方法,具体实现如下:
inArray:function(elem,array){
for(vari=0,length=array.length;i<length;i++)
//Use===becauseonIE,window==document
if(array[i]===elem)
returni;
return-1;
}
一目了然,返回elem的索引值。
二、数据缓存
1. 【data(name)】和【data(name,value)】
data(name)返回元素上储存的相应名字的数据,可以用data(name, value)来设定。
data(name,value)在元素上存放数据,同时也返回value。
例子
HTML代码 | jQuery代码 |
<div></div> |
|
<div></div> |
|
现在来看看data方法的具体实现:
jQuery.fn.extend({
data:function(key,value){
varparts=key.split(".");
parts[1]=parts[1]?"."+parts[1]:"";
if(value===undefined){
vardata=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);
if(data===undefined&&this.length)
data=jQuery.data(this[0],key);
returndata===undefined&&parts[1]?
this.data(parts[0]):
data;
}else
returnthis.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){
jQuery.data(this,key,value);
});
},
removeData:function(key){
returnthis.each(function(){
jQuery.removeData(this,key);
});
}
});
当我们要在元素上存放数据的时候,比如 $("div").data("blah","hello"); 将执行这句代码:
return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){jQuery.data( this, key, value );});
我们看下jQuery.data(this,key,value);这句代码,继续展开jQuery.data方法的具体实现以及相关其他代码:
functionnow(){
return+newDate;
}
varexpando="jQuery"+now(),uuid=0,windowData={};
jQuery.extend({
cache:{},
data:function(elem,name,data){
elem=elem==window?
windowData:
elem;
varid=elem[expando];
//在元素上产生唯一的ID
if(!id)
id=elem[expando]=++uuid;
//当我们试着访问一个键是否含有值的时候,如果不存在jQuery.cache[id]值,初始化jQuery.cache[id]值
if(name&&!jQuery.cache[id])
jQuery.cache[id]={};
//防止一个undefined的值覆盖jQuery.cache对象
if(data!==undefined)
jQuery.cache[id][name]=data;
returnname?
jQuery.cache[id][name]:
id;
}
});
其中这句代码
if ( data !== undefined )
jQuery.cache[ id ][ name ] = data;
将data存储在cache对象中。
当我们需要返回元素上储存的相应名字的数据的时候,比如 $("div").data("blah"); 主要将执行这句代码:
data = jQuery.data( this[0], key );
最后将返回一个保存在 jQuery.cache[ id ][ name ] 中的数据。
2. 【removeData(name)】
在元素上移除存放的数据。具体实现如下:
removeData:function(key){
returnthis.each(function(){
jQuery.removeData(this,key);
});
}
继续展开jQuery.removeData方法的具体实现:
removeData:function(elem,name){
elem=elem==window?
windowData:
elem;
varid=elem[expando];
if(name){
//elem是否存在元素cache
if(jQuery.cache[id]){
//移除一个具有特定键的元素数据
deletejQuery.cache[id][name];
//将键值置空,准备移除元素cache
name="";
for(nameinjQuery.cache[id])
break;
if(!name)
jQuery.removeData(elem);
}
}else{
//Cleanuptheelementexpando
try{
deleteelem[expando];
}catch(e){
//IEhastroubledirectlyremovingtheexpando
//butit'sokwithusingremoveAttribute
if(elem.removeAttribute)
elem.removeAttribute(expando);
}
//完全移除元素cache
deletejQuery.cache[id];
}
}
通过调用 delete jQuery.cache[ id ][ name ]; 和 delete jQuery.cache[ id ];,移除所有该元素上的cache数据;
3. 【queue([name])】,【queue([name],callback)】和【queue([name],queue】
例子
HTML 代码 | jQuery 代码 |
<style> | $("#show").click(function () { |
<style> | $(document.body).click(function () { |
<style> | $("#start").click(function () { |
由于div节点产生动画效果,每条动画就调用一个jQuery.data方法,将每条动作保存在jQuery.cache中,就形成了缓存队列。至于div节点产生动画效果如何调用jQuery.data方法会在以后的章节中介绍。
请看第一行的例子,可以看到这里包含7条动作效果,也就是在还没有执行它们以前,如果调用 var n = $("div").queue("fx"); 返回一个队列对象n,查看该对象的长度,发现队列长度为7,而每执行完一条动作,队列长度就会减1。
再看第二行的例子,queue的第一个参数为一个函数,当执行完这个自定义函数后,要继续执行队列,这要调用dequeue方法。
再看第三行的例子,queue的第二个参数为一个数组,实际上它可以是一个新队列或者现有队列去替代当前队列,其中新队列或者现有队列的值和queue(callback)相同。
现在看看queue的具体实现:
queue:function(type,data){
if(typeoftype!=="string"){
data=type;
type="fx";
}
if(data===undefined)
{
returnjQuery.queue(this[0],type);}
returnthis.each(function(){
varqueue=jQuery.queue(this,type,data);
if(type=="fx"&&queue.length==1)
queue[0].call(this);
});
}
其中 if(typeof type !== "string") { data = type; type = "fx"; } 可以得出fx为默认的队列名称。继续查看jQuery.queue方法:
queue:function(elem,type,data){
if(elem){
type=(type||"fx")+"queue";
varq=jQuery.data(elem,type);
if(!q||jQuery.isArray(data))
q=jQuery.data(elem,type,jQuery.makeArray(data));
elseif(data)
q.push(data);
}
returnq;
}
归根结底最后通过jQuery.data从jQuery.cache对象获得数据。jQuery.isArray(data) 判断是否是新队列或者现有队列数组。
4. 【dequeue([name])】
从队列最前端移除一个队列函数,并执行它。
dequeue的具体实现为:
dequeue:function(type){
returnthis.each(function(){
jQuery.dequeue(this,type);
});
}
然后查看jQuery.dequeue方法的具体实现如下:
dequeue:function(elem,type){
varqueue=jQuery.queue(elem,type),
fn=queue.shift();
if(!type||type==="fx")
fn=queue[0];
if(fn!==undefined)
fn.call(elem);
}
可以发现最后通过 fn=queue.shift();或者fn=queue[0]得到队列的第一个元素,然后fn.call(elem);去执行它。
好了,jQuery对象访问和数据缓存的原理机制就是这样的。
系列文章:
jQuery.API源码深入剖析以及应用实现(1) - 核心函数篇
jQuery.API源码深入剖析以及应用实现(2) - jQuery对象访问和数据缓存
- ››jquery .ajax方法 异步表单,接收服务器返回的数据...
- ››jquery 添加\删除 cookie
- ››jquery 正则表达式判断是否为正确邮箱格式
- ››jQuery EasyUI 数字框(NumberBox)用法
- ››JQuery中对option的添加、删除、取值
- ››JQuery实现下拉,单选,复选三大控件方法,
- ››jquery实现判断输入文字个数的代码
- ››jQuery bxCarousel实现图片滚动切换效果
- ››jQuery弹性滑动导航菜单
- ››jquery实现全选反选功能
- ››jQuery 屏蔽单个元素使用户无法点击
- ››jquery做复选框的全选、全部选、反选更加简单
更多精彩
赞助商链接