引入缓存的作用
- 允许我们在dom元素添加自定义的属性,避免循环引用的的内存泄漏风险
- 用于存储跟dom节点相关的数据,包括事件、动画等
- 一种低耦合的方式让dom和缓存数据能够联系起来
这里面有两个概念需要知悉
dataPriv: 一个Data实例,保存jQuery内部数据,如果jQuery的事件、动画、等数据都由这个访问器保存和获取
dataUser: 一个Data实例,保存用户通过jQuery的API存储的数据
使用方式
jQuery.data(ele, key, value) 或者 $.data(ele, key, value)
var obj = {};
jQuery.data(obj, 'name', 'franki');
代码执行顺序为:
jQuery.data -> Data.prototype.access -> Data.prototype.set -> Data.prototype.cache -> 赋值
代码片段分析:
access 判断操作
access: function(owner, key, value) {
// 根据传入的key value 判断是进行数据读取还是数据存储
if (
key === undefined ||
(key && typeof key === 'string' && value === undefined)
) {
return this.get(owner, key);
}
this.set(owner, key, value);
return value !== undefined ? value : key;
}
set 操作
// 主要进行数据存储操作
set: function(owner, data, value) {
var prop,
cache = this.cache(owner);
if (typeof data === 'string') {
cache[camelCase(data)] = value;
} else {
for (prop in data) {
cache[camelCase(prop)] = data[prop];
}
}
return cache;
},
cache 操作
// 判断当前owner是否存在缓存,若有直接返回返回缓存的数据,this.expando是判断用户设置缓存唯一的表示,保证
// 每次或者其他用户都不一样,确保数据正确性
cache: function(owner) {
var value = owner[this.expando];
if (!value) {
value = {};
if (acceptData(owner)) {
if (owner.nodeType) {
owner[this.expando] = value;
} else {
Object.defineProperty(owner, this.expando, {
value: value,
configurable: true
});
}
}
}
return value;
},
使用方式
jQuery.data(ele, key) 或者 $.data(ele, key)
var obj = {};
jQuery.data(obj, 'name');
代码执行顺序为:
jQuery.data -> Data.prototype.access -> Data.prototype.get
大体同上面的分析类似,只是set的操作,换成get操作
具体如下
get 操作
get: function(owner, key) {
return key === undefined
? this.cache(owner)
: // Always use camelCase key (gh-2257)
owner[this.expando] && owner[this.expando][camelCase(key)];
},
上面的调用方式是直接通过$.data() 或者是 jQuery.data()的方式去调用的,下面来介绍通过实例的方式去调用
$(‘body’).data()
代码执行顺序为:$(‘div’) -> .data -> access -> 执行access参数里面的回调函数 -> 返回结果
jQuery.fn.extend({
data: function(key, value) {
var i,
name,
data,
elem = this[0],
attrs = elem && elem.attributes;
return access(
this,
function(value) {
var data;
if (elem && value === undefined) {
data = dataUser.get(elem, key);
if (data !== undefined) {
return data;
}
data = dataAttr(elem, key);
if (data !== undefined) {
return data;
}
return;
}
this.each(function() {
dataUser.set(this, key, value);
});
},
null,
value,
arguments.length > 1,
null,
true
);
},
}
上面的代码指明了数据的获取方式,首先从全局的用户缓存里面取,如果有就则返回用户缓存的值,如果没有就去dataAttr里面找,找到则返回。
dataAttr 代码分析
function dataAttr(elem, key, data) {
var name;
// 从html5 标签 data-* 获取值
if (data === undefined && elem.nodeType === 1) {
name = 'data-' + key.replace(rmultiDash, '-$&').toLowerCase();
data = elem.getAttribute(name);
if (typeof data === 'string') {
try {
data = getData(data);
} catch (e) {}
dataUser.set(elem, key, data);
} else {
data = undefined;
}
}
return data;
}
jQuery.data() 与 .data() 区别
- 看jQuery.data(element,[key],[value]),每一个element都会有自己的一个{key:value}对象保存着数据,所以新建的对象就算有key相同它也不会覆盖原来存在的对象key所对应的value,因为新对象保存是是在另一个{key:value}对象中
- $(“div”).data(“a”,”aaaa”) 它是把数据绑定每一个匹配div节点的元素上
总结:
jQuery的cache其实就围绕set get方法进行数据的读写操作,只不过根据调用方式不同,数据存储的地方不同罢了。