您好,欢迎访问一九零五行业门户网

jQuery对象数据缓存Cache原理及jQuery.data方法区别介绍_jquery

网上有很多教你怎么使用jquery.data(..)来实现数据缓存,但有两个用户经常使用的data([key],[value])和jquery.data(element,[key],[value])几乎没有什么文章说清楚它们两的区别,所以我用到了,研究下分享给大家。
$().data([key],[value])与jquery.data(element,[key],[value])的区别
这两个函数都是用来在元素上存放数据也就平时所说的数据缓存,都返回jquery对象,当时我分别在使用它俩的时候真的吓我一跳,区别可大了,真是不用不知道,一用吓一跳。看例子先吧,后再根据源代码分析。
js代码:
复制代码 代码如下:
test2
test3
test
aaaa
看了上面的例子是不是发现data([key],[value])与jquery.data(element,[key],[value])两个根本就不一样了对吧?它们之间到底有没有关系呢。怎么data([key],[value])会覆盖前面key相同的值呢?
而jquery.data(element,[key],[value])只要是绑定到不同的对象上都不会造成覆盖。是这样吗?那来研究下它们的源代码吧。
先看jquery.data(element,[key],[value])源代码。
js代码:
复制代码 代码如下:
jquery.extend({
cache: {},
// please use with caution
uuid: 0,
// unique for each copy of jquery on the page
// non-digits removed to match rinlinejquery
expando: jquery + ( jquery.fn.jquery + math.random() ).replace( /\d/g, ),
....
data: function( elem, name, data, pvt /* internal use only */ ) {
// 是否可以附加数据,不可以则直接返回
if ( !jquery.acceptdata( elem ) ) {
return;
}
var privatecache, thiscache, ret,
//jquery.expando这是一个唯一的字符串,是这介jquery对象产生的时候就生成了。
internalkey = jquery.expando,
getbyname = typeof name === string,
// 必须区分处理dom元素和js对象,因为ie6-7不能垃圾回收对象跨dom对象和js对象进行的引用属性
isnode = elem.nodetype,
// 如果是dom元素,则使用全局的jquery.cache
// 如果是js对象,则直接附加到对象上
cache = isnode ? jquery.cache : elem,
// only defining an id for js objects if its cache already exists allows
// the code to shortcut on the same path as a dom node with no cache
id = isnode ? elem[ internalkey ] : elem[ internalkey ] && internalkey,
isevents = name === events;
// 避免做更多的不必要工作,当尝试在一个没有任何数据的对象上获取数据时
// 对象没有任何数据,直接返回
if ( (!id || !cache[id] || (!isevents && !pvt && !cache[id].data)) && getbyname && data === undefined ) {
return;
}
// id不存在的话就生成一个
if ( !id ) {
// only dom nodes need a new unique id for each element since their data
// ends up in the global cache
if ( isnode ) {
// 如果是dom元素则在元素上产生唯一的id 并且以jquery.expando
//为属性值为id保存在elem元素上,以便以后再根据jquery.expando来查找id。
elem[ internalkey ] = id = ++jquery.uuid;
} else {
// js对象则直接使用jquery.expando,既然是直接附加到对象上,又何必要id呢?
// 避免与其他属性冲突!
id = internalkey;
}
}
//// 当我们试着访问一个键是否含有值的时候,如果不存在jquery.cache[id]值,
// 初始化jquery.cache[id]值 为一个空对象{}
if ( !cache[ id ] ) {
cache[ id ] = {};
if ( !isnode ) {
cache[ id ].tojson = jquery.noop;
}
}
// an object can be passed to jquery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
// data是接收对象和函数,浅拷贝
if ( typeof name === object || typeof name === function ) {
if ( pvt ) {
cache[ id ] = jquery.extend( cache[ id ], name );
} else {
cache[ id ].data = jquery.extend( cache[ id ].data, name );
}
}
/ 存储对象,存放了所有数据的映射对象
privatecache = thiscache = cache[ id ];
// jquery data() is stored in a separate object inside the object's internal data
// cache in order to avoid key collisions between internal data and user-defined
// data.
// jquery内部数据存在一个独立的对象(thiscache.data==thiscache[ internalkey ])
//上,为了避免内部数据和用户定义数据冲突
if ( !pvt ) {
// 存放私有数据的对象不存在,则创建一个{}
if ( !thiscache.data ) {
thiscache.data = {};
}
// 使用私有数据对象替换thiscache
thiscache = thiscache.data;
}
// 如果data不是undefined,表示传入了data参数,则存储data到name属性上
if ( data !== undefined ) {
// jquery.camelcase( name )作用是如果传入的是object/function,不做转换,
//只有传入的name是字符串才会转换。所以最终保存下来的是key/value对;
thiscache[ jquery.camelcase( name ) ] = data;
}
//从这以后下面的代码都是处理data: function( elem, name)data为空,求返回值data的情况了。
if ( isevents && !thiscache[ name ] ) {
return privatecache.events;
}
// 如果name是字符串,则返回data
// 如果不是,则返回整个存储对象
if ( getbyname ) {
// first try to find as-is property data
ret = thiscache[ name ];
// test for null|undefined property data
if ( ret == null ) {
// try to find the camelcased property
ret = thiscache[ jquery.camelcase( name ) ];
}
} else {
ret = thiscache;
}
return ret;
},
............
});
请看图
看jquery.data(element,[key],[value])源代码后可以知道,每一个element都会有自己的一个{key:value}对象保存着数据,所以新建的对象就算有key相同它也不会覆盖原来存在的对象key所对应的value,因为新对象保存是是在另一个{key:value}对象中。
接下来要分析data([key],[value])源代码使用到了each(callback),在分析它之前先看下each(callback)用法和源代码。
js代码:
复制代码 代码如下:
test2
test3
test
aaaa
现在来看each方法的具体实现如下:
jquery.fn = jquery.prototype = {
each: function( callback, args ) {
return jquery.each( this, callback, args );
}
}
可以看到它返回的是全局的each方法,并且将自身jquery对象做为参数给它,全局的each方法的具体实现如下:
// args 作为内部成员的调用来使用
each: function( object, callback, args ) {
var name, i = 0, length = object.length; // 当object为jquery对象时,length非空
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i if ( callback.apply( object[ i++ ], args ) === false )
break;
// 以下是客户端程序进行调用
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
// i表示索引值,value表示dom元素
for ( var value = object[0];
i value = object[++i] ){}
}
return object;
}
现在我们关注下 for ( var value = object[0]; i 得到遍历整个jquery对象中对应的每个dom元素,通过callback.call( value,i,value); 将callback的this对象指向value对象,并且传递两个参数,i表示索引值,value表示dom元素;其中callback是类似于 function(index, elem) { } 的方法。所以就得到 $().each(function(index, elem){ });
再来看看data([key],[value])的源代码
js代码:
复制代码 代码如下:
jquery.fn.extend({
data: function( key, value ) {
var parts, part, attr, name, l,
elem = this[0],
i = 0,
data = null;
// gets all values
if ( key === undefined ) {
.....//处理没有key的情况,这里不是我们要讨论的
return data;
}
// sets multiple values
if ( typeof key === object ) {
return this.each(function() {
jquery.data( this, key );
});
}
parts = key.split( ., 2 );
parts[1] = parts[1] ? . + parts[1] : ;
part = parts[1] + !;
return jquery.access( this, function( value ) {
if ( value === undefined ) {
。。。//这里是没有value时,是索取返回值的情况,这不是我们讨论
}
parts[1] = value;
//如果我使用用$(div).data(a,aaa)),下面调用each前的this指的是$(div)这返回的对象,
this.each(function() {//注意了,这里是以每一个匹配的元素作为上下文来执行一个函数
var self = jquery( this );
self.triggerhandler( setdata + part, parts );
//这里在元素上存放数据,本质还是委托data(element,[key],[value])来做的。
//看前面有分析过了。
//下面data( this, key, value )里的this指的是遍历整个jquery对象中对应的每个dom元素
//$(div)它对应页面中一个数组。
jquery.data( this, key, value );//这名句会被循环多次执行,也就是保存数据。
//这里就是核心一句话。但要清楚看上面了它是在each(functipn(){})中的。
self.triggerhandler( changedata + part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
//在元素上移除存放的数据。具体实现如下:
removedata: function( key ) {
return this.each(function() {
jquery.removedata( this, key );
});
}
});
如果对于data([key],[value])的源代码不是很了解,好吧,我就用一个例子来模仿实现它吧。
js代码:
复制代码 代码如下:
test2
test3
test
aaaa
现在对data([key],[value])与jquery.data(element,[key],[value])都有了解了吧,如果还是半懂,再回头多看一遍,耐心地理解一下。其实表面上很不一样。但本质上还是有联系的,现在明白原理后就可以请放心地使用了。jquery.data(element,[key],[value])只把数据绑定到参数element节点上。data([key],[value])
如$(div).data(a,aaaa)它是把数据绑定每一个匹配div节点的元素上。
附加说明下,文中所分析用到的是jquery-1.7.2.js的源代码。下载地址:http://demo.jb51.net/jslib/jquery/jquery-1.7.2.min.js
其它类似信息

推荐信息