首頁 > web前端 > js教程 > 關於jQuery物件資料緩存Cache原理以及jQuery.data詳解_jquery

關於jQuery物件資料緩存Cache原理以及jQuery.data詳解_jquery

WBOY
發布: 2016-05-16 17:38:09
原創
1251 人瀏覽過

網路上有很多教你怎麼使用jQuery.data(..)來實現資料緩存,但有兩個使用者常用的data([key],[value])和jQuery.data(element,[key] ,[value])幾乎沒有什麼文章說清楚它們兩的差別,所以我用到了,研究下分享給大家。
$("").data([key],[value])與jQuery.data(element,[key],[value])的差異
這兩個函數都是用來在元素上存放資料也就平時所說的資料快取,都返回jQuery對象,當時我分別在使用它倆的時候真的嚇我一跳,差別可大了,真是不用不知道,一用嚇一跳。看例子先吧,後再根據原始碼分析。

Js代碼:

複製程式碼 程式碼如下:

test2

test3

test

aaaa


<script> <BR>$(document).ready(function(){ <BR>$("#test") .click(function(){ <BR>alert("JQUERY"); <br><br>var e=$("div");//定義了兩jquery物件<BR>var w=$("divvar w=$("div");//定義了兩jquery物件<br>var w=$("divvar w=$("div ");//e是不等於w的。<br><BR>// 先使用data([key],[value])用法。<BR>$(e).data("a","aaaa ");//分別在e和w上保存Key一樣的數據, <BR>$(w).data("a","wwww");// 看它是否會覆蓋前面的,雖然是保存在不同物件上。 w)//false <BR>alert($(w).data("a"));//這裡也是wwww; <BR><br>//使用jQuery.data(element,[key],[value ])來存放資料。 ,"dddd");// 看它是否會覆蓋前面的,雖然是保存在不同物件上。輸出cccc <br>alert($.data(w,"b"));//這輸出dddd <BR><BR>}); <BR>}); <BR></script>



看了上面的範例是不是發現data([key],[value])與jQuery.data(element,[key],[value])兩個根本就不一樣了對吧?它們之間到底有沒有關係呢。怎麼data([key],[value])會覆寫前面key相同的值呢?

而jQuery.data(element,[key],[value])只要是綁定到不同的物件上都不會造成覆蓋。是這樣嗎?那就來研究下它們的原始碼吧。

先看jQuery.data(element,[key],[value])原始碼。


Js代碼:

複製程式碼

程式碼如下:

jQuery.extend({
cache: {},

// Please use with caution
cache: 0,

// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
expando: "jQuery" ( jQuery.fn.jquery Math.random() ).replace( /D/g, "" ),

....
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
// 是否可以附加數據,不可以則直接回傳
if ( !jQuery.acceptData( elem ) ) {
return;
}

var privateCache, thisCache, ret,
//jQuery.expando這是唯一的字串,是唯一的字串,是唯一的字串這介jquery物件產生的時候就產生了。 ,因為IE6-7無法垃圾回收物件跨DOM物件和JS物件進行的參考屬性
isNode = elem.nodeType,

// 如果是DOM元素,則使用全域的jQuery.cache
// 如果是JS對象,則直接附加到對象
cache = isNode ? jQuery.cache : elem,

// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
isEvents = name === "events";

// 避免做更多的不必要工作,當嘗試在一個沒有任何數據的對像上獲取數據時
// 對象沒有任何數據,直接返回
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
// id不存在的話就產生一個
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if (>if (>if (>if isNode ) {
// 如果是DOM元素則在元素上產生唯一的ID 並且以jQuery.expando
//為屬性值為id保存在elem元素上,以便以後再根據jQuery.expando來查找ID。
elem[ internalKey ] = id = jQuery.uuid;
} else {
// JS物件則直接使用jQuery.expando,既然是直接附加到物件上,又何必要id呢?
// 避免與其他屬性衝突!
id = internalKey;
}
}

//// 當我們試著存取一個鍵是否含有值的時候,如果不存在jQuery.cache[id]值,
// 初始化jQuery.cache[id]值為一個空物件{}
if ( !cache[ id ] ) {
cache[ id ] = {};

if ( ! isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}

// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
// data是接收物件和函數,淺拷貝
if ( typeof name === "object" || typeof name === "function " ) {
if ( pvt ) {
cache[ id ] = jQuery.extend( cache[ id ], name );
} else {
cache[ id ].data = jQuery.extend ( cache[ id ].data, name );
}
}
/ 儲存對象,存放了所有資料的映射對象
privateCache = thisCache = cache[ id ];

// jQuery data() is stored in a separate object inside the object's internal data
// cache in order to avoid key collisions between internal data and user-defined
// data. //上,為了避免內部資料與使用者定義資料衝突
if ( !pvt ) {
// 存放私有資料的物件不存在,則建立一個{}
if ( !thisCache.data ) {
thisCache.data = {};
}
// 使用私人資料物件取代thisCache
thisCache = thisCache.data;
}
// 如果data不是undefined,表示傳入了data參數,則儲存data到name屬性上
if ( data !== undefined ) {
/ / jQuery.camelCase( name )作用是如果傳入的是object/function,不做轉換,
//只有傳入的name是字串才會轉換。所以最後保存下來的是key/value對;
thisCache[ jQuery.camelCase( name ) ] = data;
}

//從這以後下面的程式碼都是處理data: function ( elem, name)data為空,求傳回值data的情況了。

if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}

// 如果name是字串,則回傳data
/ / 如果不是,則傳回整個儲存物件
if ( getByName ) {

// First Try to find as-is property data
ret = thisCache[ name ];

// Test for null|undefined property data
if ( ret == null ) {

// Try to find the camelCased property
ret = thisCache[ jQuery.camelCase( name ) ] }
} else {
ret = thisCache;
}

return ret;
},
............
});

請看圖。

看jQuery.data(element,[key],[value])原始碼後可以知道,每一個element都會有自己的一個{key:value}物件保存著數據,所以新建的物件就算有key相同它也不會覆寫原來存在的物件key所對應的value,因為新物件保存是在另一個{key:value}物件中。

接下來要分析data([key],[value])原始碼使用到了each(callback),在分析它之前先看下each(callback)用法和原始碼。

Js代碼:

複製程式碼 程式碼如下:

test2

test3

test

aaaa


<script> <BR>$(document).ready(function(){ <BR>$("#test") .click(function(){ <BR>alert("JQUERY"); <br><br>var i=0; <BR>$("#abc3").each(function() { <BR>alert( i);//只輸出1;因為只有一個<div id="abc3"> <BR>}); <BR>alert("----"); <BR>var j=0; <BR> $("div").each(function() { <BR>alert( j);//分別輸出1,2,3;因為有三個<div>所以循環三次<BR>}); <BR> }); <BR>}); <BR></script>

現在來看each方法的具體實作如下:
jQuery.fn = jQuery.prototype = {
each: function ( callback, args ) {
return jQuery.each( this, callback, args );
}
}

可以看到它回傳的是全域的each方法,並且將自身的each方法,並且將自己jQuery物件做為參數給它,全域的each方法的具體實作如下:
// args 作為內部成員的呼叫來使用
each: function( object, callback, args ) {
var name, i = 0, length = object.length; // 當object為jQuery物件時,length非空

if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i } else
for ( ; i } else
for ( ; i } ( callback.apply( object[ i ], args ) === false )
break;
// 以下是客戶端程式進行呼叫
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
// i表示索引值,value表示DOM元素
for ( var value = object[0];
i value = object[ i] ){}
}
return object;

}

現在我們關注下for ( var value = object[0]; i 得到遍歷整個jQuery物件中對應的每個DOM元素,透過callback.call( value,i,value); 將callback的this物件指向value對象,並且傳遞兩個參數,i表示索引值,value表示DOM元素;其中callback是類似於function(index, elem) { } 的方法。所以就得到 $("").each(function(index, elem){ });

再來看看data([key],[value])的原始碼

Js代碼:
複製程式碼 程式碼如下:

jQuery.fn.extend({
data: function( key, value ) {
var parts, part, attr, name, l,
elem = this[0],
i = 0,
data = null;

// Gets all values
if ( key === undefined ) {
.....//處理沒有Key的情況,這裡不是我們要討論的

return data;
}

// Sets multiple values
if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}

parts = key.split( ".", 2 );
parts[1] = parts[1] ? "." parts[1] : "";
part = parts[1] "!";

return jQuery.access( this, function( value ) {

if ( value === undefined ) {
。 。 🎜>
parts[1] = value;

//如果我用$("div").data("a","aaa")),下面調用each前的this指的是$("div")這返回的對象,
this.each(function() {//注意了,這裡是以每一個匹配的元素作為上下文來執行一個函數
var self = jQuery ( this );

self.triggerHandler( "setData" part, parts );

//這裡在元素上存放數據,本質還是委託data(element,[key],[value ])來做的。 🎜>//$("div")它對應頁面中一個
陣列。
jQuery.data( this, key, value );//這名句子會被迴圈多次執行,也就是儲存資料
//這裡就是核心一句話。但要清楚看上面了它是在each(functipn(){})中的。
self.triggerHandler( "changeData" part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
/ /在元素上移除已存放的資料。具體實作如下:
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
}
});
}
}
});
}
}
}); }

}

}); >});

如果對於data([key],[value])的原始碼不是很了解,好吧,我就用一個例子來模仿實現它吧。 Js代碼:
複製程式碼


程式碼如下:


test2

test3

test

aaaa


<script> <BR>$(document).ready(function(){ <BR>$("#test") .click(function(){ <BR>alert("JQUERY"); <BR><BR>var i=0; <BR>$("#abc3").each(function() { <br>alert( i);//只輸出1;因為只有一個<div id="abc3"> <br>}); <BR>alert("----"); <BR>var j=1; <BR> $("div").each(function() {//以每一個符合的元素作為上下文來執行這個函數<BR><BR>$.data(this,"a","wwww");//這裡的this是指$("div"), <BR>//分別遍歷每一個匹配的元素給它們每一個物件{}都保存一個key/value <BR>alert(j );//分別輸出1 ,2 ,3 因為有三個<div>元素<br>}); <br>alert($("#test").data("a"));//回傳wwww, <BR>//是不是很驚呀,我沒有保存在它身上啊,怎麼也有值,很明顯是它是查這個div節點上有沒有, <BR>//肯定是有值了,因為上面給循環保存在div這Dom結點上了。 div").data("a"));//返回wwww, <BR>//這裡也是一樣因為是div節點上都保存了"a"="wwww"這樣一個鍵值對了。<BR> }); <BR>}); </script>



現在對data([key],[value])與jQuery.data(element,[key],[value])都有了解了吧,如果還是半懂,再回頭多看一遍,耐心地理解一下。其實表面上很不一樣。但本質上還是有連結的,現在明白原理後就可以請放心地使用了。 jQuery.data(element,[key],[value])只把資料綁定到參數element節點。 data([key],[value])如$("div").data("a","aaaa")它是把資料綁定每一個符合div節點的元素上。 附加說明下,文中所分析用到的是 jquery-1.7.2.js的原始碼。下載網址:

http://demo.jb51.net/jslib/jquery/jquery-1.7.2.min.js

 
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板