为什么会有这么一个模块?
1.有时候做前后端交互会在DOM元素上添加一些自定义的属性,如<div user-id="1"></div>
。为了避免增加一堆的自定义属性标签,所以才有了这么一个模块。
2.避免内存泄漏。
静态与实例方法
1.jQuery.data()
静态方法有三种重载:
jQuery.data(elem, key, value)给elem设置属性
jQuery.data(elem, data)给elem设置多个属性,data为json格式
jQuery.data(elem, key)获取elem的某个属性值
2.$().data()
实例方法同样有三种重载:
$().data(key, value)给筛选到所有DOM元素的设置属性
$().data(data)给筛选到所有DOM元素的设置多个属性,data为json格式
$().data(key)获取第一个DOM元素的属性值
Data类
不管是静态方法还是实例方法都是基于Data类实现的,贴出代码
jQuery.extend({
// 唯一标识,类似HashCode
expando: "jQuery" + (Math.random().toString()).replace(/\D/g, "")
})
// 数据缓存Data类
function Data() {
this.expando = jQuery.expando + Data.uid++;
}
Data.uid = 1; // 用于自增
Data.prototype = {
// 获取缓存&初始化缓存
cache: function(owner) {
var value = owner[this.expando];
// 初始化缓存
if(!value) {
value = {};
if (owner.nodeType) { // owner是DOM元素节点
owner[this.expando] = value;
} else { // owner是对象或者方法之类的
Object.defineProperty(owner, this.expando, {
value: value,
configurable: true
})
}
}
return value;
},
// 获取属性
get: function(owner, key) {
return key === undefined ?
this.cache(owner) :
this.cache(owner)[key];
},
// 设置属性
set: function(owner, data, value) {
var cache = this.cache(owner);
if (typeof data == 'string') { // 设置单个属性
cache[data] = value;
} else { // 设置多个属性,data传入对象
for (var prop in data) {
cache[prop] = data[prop];
}
}
},
// 通过参数的数量和类型来调用get或set
// key===undefined时,调用get方法
// key类型为string且value===undefined,调用get方法
// 其他均调用set方法
access: function(owner, key, value) {
if (key === undefined || (typeof key === 'string' && value === undefined)) {
return this.get(owner, key);
}
this.set(owner, key, value);
return value !== undefined ? value : key;
}
}
cache()
用于获取owner的缓存对象,owner可以是DOM元素、JavaScript对象、方法甚至是一个变量。get()
和set()
分别用于获取和设置属性,剩下的access()
方法就是将get()
和set()
合并了以下。当然还要其他的一些方法,但最主要的方法就那3个:cache()
、get()
和set()
。
静态方法
var dataUser = new Data();
jQuery.extend({
data: function( elem, name, data ) {
return dataUser.access( elem, name, data );
}
})
非常简单,只用一个方法就能解决get和set,这就是access()
存在的意义
实例方法
jQuery.fn.extend({
data: function(key, value) {
// get
if(key === undefined || (typeof key === 'string' && value === undefined)) {
return dataUser.get(this[0], key);
}
// set
this.each(function () {
dataUser.set(this, key, value);
})
}
})
同样的是在一个方法解决get和set,jQuery的实例方法源码远比上面这个多得多,我看了半天也没看出来多的代码做了些什么,不过没关系,不用在意这些细节,整体的实现思路已经弄清楚了。最核心的就是Data类,静态方法和示例方法就是借助这个Data类去实现的。