demo
(function(){
var $ul = $("<ul></ul>");
for(var i=0; i<10; i++){
var $li = $("<li></li>");
var $a = $("<a href='javascript:;'>按钮"+i+"</a>");
$a.data("num",i);
$li.append($a);
$ul.append($li);
}
$("body").append($ul);
$("a").click(function(e){
console.log($(this).data("num"));
});
}());
学习这篇博客 http://www.cnblogs.com/ellisonDon/archive/2012/08/12/2635316.html
jQuery源码(加上自己备注)
function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !acceptData( elem ) ) {
return;
}
var ret, thisCache,
internalKey = jQuery.expando,
isNode = elem.nodeType,
cache = isNode ? jQuery.cache : elem,
//若elem是DOM元素,将jQuery下的cache赋值给cache;反之,可能是一个普通的js对象,那么将这个对象赋值给cache,这种赋值方式,jQuery.cache或elem会随着cache变化而变化
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
if ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) &&
data === undefined && typeof name === "string" ) {
return;
}
if ( !id ) {
if ( isNode ) {
id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
//若这个DOM元素第一次缓存数据,则新建一个id,并顺带赋值elem[ internalKey ]
} else {
id = internalKey;
}
}
if ( !cache[ id ] ) {
cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; //给cache添加一个key为id的属性
}
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 );
//为cache[id]添加一个key为data的属性,用jQuery.extend()将以前的缓存和新传入的“object或者function”合并
}
}
thisCache = cache[ id ];
// data.
if ( !pvt ) {
if ( !thisCache.data ) {
thisCache.data = {};
}
thisCache = thisCache.data;
}
if ( data !== undefined ) {
thisCache[ jQuery.camelCase( name ) ] = data;
}
if ( typeof name === "string" ) { //传入key为字符串
ret = thisCache[ name ]; //先看以前有没有传过
if ( ret == null ) { //没传过
ret = thisCache[ jQuery.camelCase( name ) ]; //现在传
}
} else {
ret = thisCache;
}
return ret;
}
可以做个测试,检验附加给dom元素的数据是否添加到jQuery的$.cache对象(jQuery缓存)
var mydiv = document.getElementById("mydiv");
$.data(mydiv,"name","mike");
console.log($.cache) //可以敲一下看看,如果是附加到dom元素,那么$.cache对象就会按照附加顺序,key值从1开始,依次递增,对应key值保存对应value
var div2 = document.getElementById("div2");
$.data(div2,"name","mike");
//再加一个,console.log($.cache)出来的的结果通过JSON.stringify()方法得到一下字符串
{"1":{"data":{"name":"mike"}},"2":{"data":{"name":"mike"}}}
总结: jQuery实现将数据与相应dom绑定的思路,以《jquery-1.12.3.js》源码为例,先用jQuery.expando方法生成一个随机字符串(大可不必在乎生成过程,够复杂,避免重复就可),下面以str表示这个随机字符串,实现与dom数据绑定后,将会给这个dom对象添加一个键值对,key等于str,value等于一个jQuery内部递增的整数,也就是与这个dom所关联的$.cache的ID。 也就是说,你在获取这个与这个dom元素相绑定的数据的时候,会通过s对应tr找到唯一的ID值,然后通过ID值可以访问附加在$.cache上面的对应dom元素的数据