手机版

详细介绍jQuery数据缓存模块的演进历史

时间:2021-10-07 来源:互联网 编辑:宝哥软件园 浏览:

数据缓存系统最早应该是jQuery1.2引入的,当时它的事件系统复制了大神DE的addEvent.js,但是addEvent在实现上有一个缺陷,把事件的所有回调都放在EventTarget上,会导致循环引用,如果EventTarget是窗口对象,会导致全局污染。有了数据缓存系统,除了避免这两个风险之外,我们还可以有效地保存不同方法生成的中间变量,这些中间变量将对另一个模块的方法有用,并解耦方法之间的依赖关系。对于jQuery来说,它的事件克隆甚至后来的队列实现都离不开缓存系统。JQuery1.2向核心模块添加了两个静态方法,data和removeData。不用说,数据和jQuery的其他方法一样,结合了读取和写入。jQuery的缓存系统是把所有数据放在$。缓存,然后为每个元素节点、文档对象和窗口对象分配一个UUID来使用缓存系统。UUID的属性名是一个随机的自定义属性,“jQuery”(新的Date())。getTime(),它的值是一个整数,从零开始递增。然而,UUID总是依附于一个物体。如果那个物体是一扇窗户,那不就是全球污染吗?因此,当jQuery在内部确定它是一个窗口对象时,它被映射到一个名为windowData的空对象,然后UUID被添加到其中。对于UUID,当我们第一次访问缓存系统时,我们将在$中创建一个空对象(缓存体)。缓存对象,用于放置与目标对象相关的东西。有点像在银行开户。UUID的价值在于存折。删除数据将删除不再需要保存的数据。如果数据在最后被完全删除,它就没有任何键值对,成为一个空对象。jQuery将从$中删除此对象。缓存并从目标对象中删除UUID。复制的代码如下://jquery 1 . 2 . 3 var expando=' jquery '(new date())。gettime(),uuid=0,window data={ };jquery . extend({ cache : } },data:函数(elem,name,data ) { elem=elem==window?windowData : elem//对窗口对象var id=elem[ expando]进行特殊处理;if(!Id) //如果没有UUID,新建一个id=elem[expando]=uuid;//如果你没有用美元开户。缓存,先开户如果(姓名!jquery . cache[id])jquery . cache[id]={ };//如果第三个参数不是未定义,则是写操作if (data!=undefined)jquery . cache[id][name]=data;//如果只有一个参数,返回缓存对象,两个参数返回目标数据返回名称?jquery . cache[id][name]: id;},removeData:函数(elem,name ) { elem=elem==window?windowData : elemvar id=elem[expando];If (name) {//删除目标数据if(jquery . cache[id]){ delete jquery . cache[id][name];名称=' ';for(jquery . cache[id]中的名称)break//遍历缓存。如果不为空,名称将被重写。如果不重写,那么!名称为true,//,这将导致再次调用此方法,但这一次只传递了一个参数,并且删除了缓存体,如果(!name)jquery . remove data(elem);}} else {//删除UUID,但是在IE下的元素上使用delete会抛出错误的尝试{ delete elem[expando];} catch(e){ if(elem . remove attribute)elem . remove attribute(expando);}//取消账号删除jquery . cache[id];}} }) jQuery在1.2.3中增加了两个同名的原型方法data和removeData,以方便链式操作和集中式操作。并在数据中添加getData、setData自定义事件的触发逻辑。1.3,数据缓存系统最终变成了一个module data.js(内部开发分部),增加了两组方法,命名空间中的队列和出列,原型中的队列和出列。队列的目的很明显,就是缓存一组数据,为动画模块服务。出列是从一组数据中删除一个。

复制代码如下://jquery 1 . 3 jquery . extend({ queue 3360 function(elem,type,data){ if(elem){ type=(type | | ' FX ')' queue ');var q=jQuery.data(elem,type);if(!Q || jQuery.isArray(data) )//确保存储一个q=jquery的数组。数据(elem,类型,jquery。makearray(数据));Else if(data )//然后在这个数据中添加一些东西q . push(data);}返回q;},出列:函数(elem,type){ var queue=jquery . queue(elem,type),fn=queue . shift();//然后删除一个。早期是放置动画的回调。删除后只需调用一次。//但是没有判断是不是功能,估计没有写入文档。它被用于内部使用如果(!type | | type===' FX ')fn=queue[0];if(fn!==undefined)fn . call(elem);} }) fx模块animate方法调用示例:复制代码如下://每个是并行处理多个动画,queue是逐个处理多个动画。这[ optall.queue===false?每个' :' queue'] (function () {/*省略*/})都会给元素添加一个自定义属性,这也会导致问题。如果我们复制这个元素,这个属性也会复制过去,导致两个元素的UUID值相同,数据操作不正确。jQuery的复制节点的早期实现非常简单。如果一个元素的cloneNode方法不能复制事件,使用cloneNode;否则,使用元素的外部HTML或父节点的内部HTML用clean方法解析新元素。然而,外部HTML和内部HTML都有明确的属性,所以需要定期清除。复制代码如下: //jQuery1.3.2 core.js克隆方法var ret=this.map(function(){ if(!jQuery.support.noCloneEvent!jquery . isxmldoc(this)){ var html=this . OuthHTML;if(!html){ var div=this . ownerdocument . create element(' div ');div . appendchild(this . clonenode(true));html=div.innerHTML}返回jQuery . clean([html . replace(/jQuery \ d='(?\d |null)'/g ' ')。replace(/^\s*/,")])[0];} else返回this . clonenode(true);});JQuery1.4发现IE在访问外部资源时可能会抛出错误的标签,比如object、ember、applet。因为旧IE的元素节点只是COM的打包,一旦引入资源,就会变成那种资源的实例,而且会有严格的访问控制,不能像普通JS对象一样随意添加成员。因此,jQuery被改变了,但是对于所有这三个标签,数据没有被缓存。JQuery创建了一个名为noData的哈希,用于检测元素节点的标签。复制的代码如下: no data : { ' embed ' : true,' object' : true,' applet' : true}。//代码防御if(elem . nodename jquery . nodata[elem . nodename . to lower case()]){ return;} jQuery1.4还提高了$。数据,允许第二个参数是一个对象,便于存储多个数据。对应于UUID的用户定义属性expando也放在命名空间下。队列和出列方法被剥离到一个新的模块中。JQuery1.43带来了三个改进。第一步是添加一个changeData自定义方法。但是,这种方法没有销量,只是产品经理的自恋。检测一个元素节点是否支持添加自定义属性的逻辑被分成一个名为acceptData的方法。因为jQuery团队发现,当对象标签加载flash资源时,仍然可以添加自定义属性,所以决定对这种情况从宽处理。IE加载flash时,需要给对象分配一个名为classId的属性,其值为CLSID :d 27 CDB 6e-AE6D-11CF-96b 8-444553540000,检测逻辑变得非常复杂。因为使用了Data和Removedata,所以可以有效地独立保存位。HTML5响应了人们随便添加自定义属性的行为,增加了一个新的缓存机制,叫做‘data-*’。当用户设置的属性以“data-”开头时,它们将被保存到元素节点的dataset对象中。所以人们可能会用HTML5方便地缓存数据,或者用jQuery的缓存系统保存数据,这样数据方法就变得有点没用了。

因此,jQuery增强了原型上的数据。当用户第一次访问这个元素节点时,他会遍历它所有以‘data-’开头的自定义属性(为了照顾旧IE,他不能直接遍历数据集),并把它们放到jQuery的缓存中。然后,当用户获取数据时,他们将首先从缓存系统中访问“data-”自定义属性,而不使用setAttribute。但是HTML5的缓存系统很弱,只能存储字符串(这当然是循环引用的原因),所以jQuery会把它们还原成各种数据类型,比如‘null’、‘false’、‘true’变成null’、‘false’、‘true’,符合数字格式的字符串会转换成数字,如果是以“{”开头,以“}”结尾,会尝试转换成对象。复制代码如下://jQuery 1.43 $ . fn . data r Brace=/(?\{.*\}|\[.*\])$/;if(data===undefined this . length){ data=jquery . data(this[0],key);if (data===undefined this[0]。nodeType===1 ) {数据=这个[0]。getAttribute(' data-' key);if(type of data==' string '){ try { data=data==' true '?true :数据==='false '?false :数据==='null '?null :jQuery.isNaN(数据)?parseFloat(数据): rbrace.test(数据)?jQuery.parseJSON(数据):数据;} catch(e){ } } else { data=undefined;}}} jQuery1.5还带来了三大改进。当时jQuery已经以1.42击败了Prototype.js,如火如荼,马太效应,用户数量暴增。其重点转变为提高性能,进入修复bug阶段(用户越多,自由测试人员越多,测试覆盖率越大)。改进的expando,最初基于时间切割,现在是版本号加随机数。因此,用户可以在一个页面中引入多个版本的jQuery。这个数据的逻辑是否提取为hasData方法,HTML5的‘data-*’属性是否也提取为私有方法dataAttr。它们都是为了逻辑清晰。DataAttr使用的是JSON.parse,因为这个JSON可能是JSON2.js引入的,但是JSON2.js有一个非常不好的地方,就是它在一系列的原生类型中加入了toJSON方法,导致for in循环判断是否为空对象时出错。JQuery被迫使用isEmptyDataObject方法进行处理。JQuery的数据缓存系统最初是为事件系统服务而区分的,后来,它成为了许多内部模块的基础设施。换句话说,框架用户的许多变量(系统数据)都会存储在其中,但是一旦发布到文档中,用户也会使用data来保存业务中使用的数据(用户数据)。过去用户少,变量名冲突的可能性小。此外,jQuery为这些系统数据精心挑选了一些不寻常的名字,比如__class__,_ _ change _ _ _,或者添加后缀,没有收到任何投诉。当jQuery成为世界级知名框架时,经常会发生用户数据名杀死系统数据名的情况,导致事件系统或其他模块瘫痪。JQuery开始改造缓存体,原来是一个对象,把任何数据都扔进去。现在它在这个缓存中创建了一个子对象,键名是random jQuery.expando值,如果是系统数据,就会存储在里面。但是,为了向前兼容,事件系统数据直接放在缓存中。至于如何区分系统数据,就很简单了,第四个参数直接加到数据方法中,真值就是系统数据。removeData时还提供了第三个参数,用于删除系统数据。还有一个new _data方法,专门用于操作系统数据。下面是缓存体的结构图:复制代码如下: varcache={ jquery143123432543360 {/* place system data */} events 3360 {/' place event name及其对应的回调列表'/}/* place user data here */} jQuery1.7对缓存体进行了改进,将系统变量放入了数据对象中。新的结构如下:复制代码如下: var cache={ data : {/* place user data */}/* place system data here */} jquery 1.8曾经添加了一个名为deleteIds的数组来重用UUID,但是时间很短。

UUID的值是由jQuery.guid增量生成的,而不是从1.8开始的jQuery.uuid。jQuery1.83之后,操作数据的实现被提取为私有方法,命名空间和原型中的方法只是一个代理,分为两组,分别是data,用户数据的removeData,_data,_removeData操作系统数据。现在光是缓存系统就是一个庞大的家族。

数据缓存说到底就是在目标对象和缓存体之间建立一一对应的关系,然后对缓存体上的数据进行操作,复杂度集中在前者。但是,在一个普通的JS对象中添加、删除、更改和检查一个属性从来都不难,用户也不会耍花招。从软件设计的原则来看,这也是最好的结果(符合KISS原则和单一职责规则)。

版权声明:详细介绍jQuery数据缓存模块的演进历史是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。