历史背景
开发中常常因为方便,把状态标志都写到dom节点中,也就是HTMLElement,缺点:
- 循环引用
- 直接暴露数据,安全性?
- 增加一堆的自定义属性标签,对浏览器来说是没意义的
- 取数据的时候要对HTML节点做操作
根本目的:
使用一种低耦合的方式让DOM和缓存数据能够联系起来
jQuery现在支持两种:
•$("ele").data()
1 jQuery.fn.extend({ 2 data: function( elem, name, data ) { 3 return jQuery.access( this, function( value )){ 4 //区别在each方法了,处理的是每一个元素dom节点 5 this.each(function() { 6 7 } 8 } 9 } 10 }, 11 ........
•jQuery.data( element, key, value )
1 jQuery.extend({ 2 acceptData: Data.accepts, 3 hasData: function( elem ){}, 4 //直接调用 data_user.access 数据类的接口,传入的是elem整个jQuery对象 5 data: function( elem, name, data ) { 6 return data_user.access( elem, name, data ); 7 }, 8 ........
区别:
•jQuery.data( element, key, value )
每一个element都会有自己的一个{key:value}对象保存着数据,所以新建的对象就算有key相同它也不会覆盖原来存在的对象key所对应的value,因为新对象保存是是在另一个{key:value}对象中
•$("div").data("a","aaaa")
它是把数据绑定每一个匹配div节点的元素上
DEMO
<div id="test">data test</div> var t1=$("#test"); var t2=$("#test"); //=======第一组========= $(''").data()方法 t1.data('a',1111); t2.data('a',2222); t1.data('a') //结果222222,被覆盖 t2.data('a') //结果222222 //=======第二组========= $.data()方法 $.data(t1,"b","1111") $.data(t2,"b","2222") $.data(t1,"b") //结果111111,未被覆盖 $.data(t2,"b") //结果222222
Data类的设计
1 function Data() { 2 Object.defineProperty(this.cache = {}, 0, { 3 get: function() { 4 return {}; 5 } 6 }); 7 this.expando = jQuery.expando + Math.random(); 8 }
1 Data.uid = 1; 2 Data.accepts = jQuery.acceptData; 3 4 Data.prototype = { 5 key: function() {}, 6 set: function() {}, 7 get: function() {}, 8 remove: function() {}, 9 hasData: function() {}, 10 access: function() {} 11 } 12 13 14 var data_priv = new Data(); 15 var data_user = new Data();
解析:
expando:
用于把当前数据缓存的UUID值做一个节点的属性给写入到指定的元素上形成关联桥梁,所以,所以元素本身具有这种属性的可能性很少,所以可以忽略冲突。
每个节点的dom[expando]的值都设为一个自增的变量id,保持全局唯一性
uid:
每个uid对应一个elem缓存数据,每个缓存对象是可以由多个name value(名值对)对组成的,而value是可以是任何数据类型的。
为了不把数据与dom直接关联,所以会把数据存储到一个cache对象上 产生一个 unlock = Data.uid++; unlock 标记号 把unlock标记号,作为一个属性值 赋予$body节点 cache缓存对象中开辟一个新的空间用于存储foo数据,this.cache[ unlock ] = {}; 最后把foo数据挂到cache上,cache[ data ] = value;