您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

jQuery数据缓存功能的实现思路及简单模拟_jquery

2024/4/6 13:55:18发布17次查看
前言
对于jquery的数据缓存,相信大家都不会陌生,jquery缓存系统不仅运用于dom元素,动画、事件等都有用到这个缓存系统。所以在平时实际应用中, 我们经常需要给元素缓存一些数据,并且这些数据往往和dom元素紧密相关。由于dom元素(节点)也是对象, 所以我们可以直接扩展dom元素的属性,但是如果给dom元素添加自定义的属性和过多的数据可能会引起内存泄漏,所以应该要尽量避免这样做。 因此更好的解决方法是使用一种低耦合的方式让dom和缓存数据能够联系起来。
另外:对于jquery.data和jquery.removedata静态方法、以及基于这两个方法的原型扩展方法的介绍和用法就不多说了,可以查看官方api文档。
实现思路
jquery提供了一套灵活和强大的缓存方法:
(1)先在jquery内部创建一个cache对象{}, 来保存缓存数据。 然后往需要进行缓存的dom节点上扩展一个值为expando的属性, 这里是”jquery” + (new date).gettime()。 注:expando的值等于”jquery”+当前时间, 元素本身具有这种属性的可能性很少,所以可以忽略冲突。
(2)接着把每个节点的dom[expando]的值都设为一个自增的变量id,保持全局唯一性。 这个id的值就作为cache的key用来关联dom节点和数据。也就是说cache[id]就取到了这个节点上的所有缓存,即id就好比是打开一个房间(dom节点)的钥匙。 而每个元素的所有缓存都被放到了一个map映射里面,这样可以同时缓存多个数据。
(3)所以cache对象结构应该像下面这样:
复制代码 代码如下:
var cache = {
uuid1: { // dom节点1缓存数据,uuid1相当于dom1[expando]
name1: value1,
name2: value2
},
uuid2: { // dom节点2缓存数据,“uuid2相当于dom2[expando]
name1: value1,
name2: value2
}
// ......
};
每个uuid对应一个elem缓存数据,每个缓存对象是可以由多个name/value(名值对)对组成的,而value是可以是任何数据类型的。
简单模拟实现
根据以上思路,就可以简单实现下jquery.data和jquery.removedate的功能了:
复制代码 代码如下:
(function(window, undefined) {
var cachedata = {}, // 用来存储数据的对象
win = window, // 把window缓存给一个变量
uuid = 0,
// 声明随机数(8位)
// 注意+new date()生成的随机数是number类型,与一个空字符串连接后(或使用tostring方法转型后)变成字符串,才可使用slice方法。
expando = cachedata + (+new date() + ).slice(-8);
// (+new date()).tostring().slice(-8)等价于expando
// 写入缓存
var data = function(elem, name, value) {
// 或使用原生方法验证字符串object.prototype.tostring.call(elem) === [object string]
// 如果elem为字符串
if (typeof elem === string) {
// 如果传入name参数,则为写入缓存
if (name !== undefined) {
cachedata[elem] = name;
}
// 返回缓存数据
return cachedata[elem];
// 如果elem为dom节点
} else if (typeof elem === object) {
var id,
thiscache;
// 如果elem不存在expando属性,则添加一个expando属性(第一次给元素设置缓存),否则直接获取已有的expando和id值
if (!elem[expando]) {
id = elem[expando] = ++uuid;
thiscache = cachedata[id] = {};
} else {
id = elem[expando];
thiscache = cachedata[id];
}
// 把一个随机数作为当前缓存对象的一个属性,利用该随机数就能找到该缓存对象
if (!thiscache[expando]) {
thiscache[expando] = {};
}
if (value !== undefined) {
// 将数据存到缓存对象中
thiscache[expando][name] = value;
}
// 返回dom元素存储的数据
return thiscache[expando][name];
}
};
// 删除缓存
var removedata = function(elem, name) {
// 如果elem为字符串,则直接删除该属性值
if (typeof elem === string) {
delete cachedata[elem];
// 如果key为dom节点
} else if (typeof elem === object) {
// 如果elem不存在expando属性,则终止执行,不用删除缓存
if (!elem[expando]) {
return;
}
// 检测对象是否为空
var isemptyobject = function(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
removeattr = function() {
try {
// ie8即标准浏览器可以直接使用delete来删除属性
delete elem[expando];
} catch (e) {
// ie6/ie7使用removeattribute方法来删除属性
elem.removeattribute(expando);
}
},
id = elem[expando];
if (name) {
// 只删除指定的数据
delete cachedata[id][expando][name];
// 如果是空对象,id所对应的数据对象全部删除
if (isemptyobject(cachedata[id][expando])) {
delete cachedata[id];
removeattr();
}
} else {
// 删除dom元素存到缓存中的所有数据
delete cachedata[id];
removeattr();
}
}
};
// 把data和removedata挂在window全局对象下,这样在外部也能访问到这两个函数
win.expando = expando;
win.data = data;
win.removedata = removedata;
})(window, undefined);
例子:
html结构:
复制代码 代码如下:
demo
js代码:
复制代码 代码如下:
window.onload = function() {
// 测试
var demo = document.getelementbyid(demo);
// 写入缓存
data(demo, myname, hcy);
console.log(data(demo, myname)); // hcy
data(demo, myblog, http://www.cnblogs.com/cystyle);
console.log(data(demo, myblog)); // http://www.cnblogs.com/cystyle
// 删除dom元素的某个缓存值
removedata(demo, myblog);
console.log(data(demo, myblog)); // undefined
console.log(data(demo, myname)); // hcy
console.log(demo[expando]); // 1
// 删除dom元素
removedata(demo);
console.log(demo[expando]); // undefined
};
firefox下例子结果截图:
对于上述例子实现jquery的简单缓存系统:先给该dom元素添加一个随机生成的属性expando,这个属性用来存放访问缓存数据的id值,就好比dom元素都有一把开启缓存保险箱的钥匙,只要有了钥匙就可以随时开启缓存保险箱。 将本来存放到dom元素中的数据都转到了缓存中,而dom元素本身只要存储一个简单的属性就可以了,这样就可以将由dom元素引起的内存泄漏(具体会发生什么状况不知道,大家都这么说~)的风险规避到最小。
结语
糊里糊涂地又到了最后,有一些术语或解释上可能存在偏差,望各位童鞋指正和给出一些建议;另外,从理论上讲, data和removedata方法可以用于任何对象的缓存, 不过如果运用于本地对象或window对象, 会存在内存泄露、循环引用等问题(^_^从网上看到的), 所以一般还是用于dom节点比较适合,还可以结合事件、动画对dom节点进行缓存数据的操作。ps:cache真的很重要!需要慢慢体会~
因为分享,所以简单;因为分享,所以快乐。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product