First, the realization principle:
For DOM elements, the DOM element is associated with the data cache object of the DOM element by assigning a unique association ID, and the association ID is appended to the attribute named with the Jquery.expando value, and the data is stored in the global cache object Jquery.cache. When reading, setting, and removing data, the associated data cache object is found from the global cache object Jquery.cache through the association ID, and then the read, set, and remove operations are performed on the data cache object.
For JavaScript objects, the data is stored directly on the property Jquery.expando of the JavaScript object. When you read, set, and remove data, you are actually reading, setting, and removing the data cache object for the JavaScript object.
To avoid conflict between the data used inside jquery and user-defined data, the data cache module stores the internal data on the data cache object and stores the custom data on the data cache object's properties.
Second, the overall structure:
Data cache
Jquery.extend ({
//Global Cached Object Cache
: {},//
unique ID seed
uuid:0,
//Unique identification of each jQuery copy in the page
expando: "JQuery" + (JQuery.fn.jquery + math.random ()). Replace (/\d/g, ""),
//whether there is an associated data
hasdata:function ( {},
//set, read custom data or internal data
data:function (elem, name, data, pvt) {},
//Remove custom data or internal data
Removedata: function (Elem, name, pvt) {},
//setting, reading internal data
_data:function (elem, name, data) {},//
whether data
can be set Acceptdata:function (elem) {}
});
JQuery.fn.extend ({
//set, read from definition data, parse HTML5 attribute data-
data:function (key,value) {},
//Remove Custom data
Removedata:function (key) {}
});
Resolves the HTML5 property data-
function dataattr (elem,key,data) {}
//Check that the data cache object is an empty
function isemptydataobject (obj {}
jquery.extend ({
//Empty data cache object
cleandata:function (elems) {}
});
Third, $.data (Elem, name, data), $.data (Elem, name)
How to use $.data (Elem, Name, data):
If you pass in the parameter name, data, set any type
How to use $.data (Elem, name):
If the key is passed in, and the parameter data is not passed in, the data of the specified name is read and returned
<!doctype html>
$.data (elem, name, data), $.data (elem, name) source analysis:
Jquery.extend ({///1) define Jquery.data (Elem, name, Data, Pvt) Data:function (Elem, name, data, PVT/* Internal use only */) {//2. Check if you can set data if (!jquery.acceptdata (Elem)) {return;///If parameter elem does not support setting data, immediately returns}//3 define local variable V Ar Privatecache, Thiscache, ret, Internalkey = Jquery.expando, getbyname = typeof name = = = "string",//We have To handle DOM nodes and JS objects differently because ie6-7//can ' t GC object references properly across the Dom-js b Oundary Isnode = Elem.nodetype,//Elem is DOM element//Only DOM nodes need the global JQuery cache; JS Object data is//attached directly to the object so GC can occur automatically cache = Isnode? JQuery.cache:elem,//If it is a DOM element, in order to avoid the browser (IE6/7) garbage collection mechanism that is caused by circular references between JavaScript and DOM elements, To store the data in the global cache object Jquery.cache, for JavaScript objects, and the recycle mechanism can occur automatically, there will be no memory leaks, so the data can be stored on JavaScript objects//only defining a ID For JS objects if it 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"; Avoid doing any more work than "We need to" when trying to get data on a//object that has no data at all//4. If the data is read, but no data is returned, the IF (!id | |!cache[id) | | (!isevents &&!pvt &&!cache[id].data))
&& getbyname && data = = undefined) {return; Getbyname && data = = Undefined if name is a string, data is undefined, indicating that the data is read//!id | | !cache[id] | | (!isevents &&!pvt &&!cache[id].data If the association ID does not exist, there is no data; if CACHE[ID] does not exist, there is no data; if it is read automatically with data, but Cache[id] . Data does not exist, stating that there is no custom datatype//5. If the association ID does not exist, assign an if (!id) {//Only DOM nodes need a new unique ID to each element since their data//ends up I
n the global cache if (Isnode) {elem[Internalkey] = id = ++jquery.uuid; for DOM elements, Jquery.uuid automatically adds 1 and attaches to the DOM element } else {id = Internalkey;//For JavaScript objects, the association ID is jquery.expando
}//6.
If the data cache object does not exist, it is initialized to empty object {} if (!cache[id]) {cache[id] = {}; Avoids exposing jQuery metadata on plain JS objects at the the object//is serialized using json.stringify if (!i Snode) {cache[id].tojson = jquery.noop//For JavaScript objects, set method Tojson to null function to avoid exposing cached data when executing json.stringify (). If an object defines a method Tojson (), json.stringify () calls this method when serializing the object to generate the JSON element of the object}//An object can is passed to Jquery.data ins Tead of a key/value pair; This is gets//shallow copied over onto the existing cache//7. If the parameter name is an object or function, the batch set data if (typeof name = = = "Object" | | typeof name = = "function") {if (pvt) {cache[id] = Jquery.extend (cache[ID], name); For internal data, merge the attributes in Parameter name into Cache[id]} else {cache[id].data = jquery.extend (cache[ID].data, name), and/or for custom data. Merges the attributes in parameter name into Cache[id].data}//8.
If the parameter data is not undefined, set a single data 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.data;
} if (data!== undefined) {thiscache[jquery.camelcase (name)] = data; }//Users should not attempt to inspect the internal events object using Jquery.data,//It is undocumented and subj ECT to change. But does anyone listen?
No. 9. Special handling Events if (isevents &&!thiscache[name]) {//If the parameter name is the string "events" and the Custom Data "events" is not set, the event wedding object is returned, where the
The event listener function.
return privatecache.events; //Check for both Converted-to-camel and non-converted the Data property names//If A Data property is specified// 10. If the parameter name is a string, read a single data if (Getbyname) {///I-Find As-is property data ret = thiscache[name]; First try to read the data for the parameter name//Test for null|undefined property data if (ret = null) {//If not fetched, the parameter name is converted to humpAttempt to read the corresponding data//try to find the Camelcased property ret = thiscache[jquery.camelcase (name)];
} else {//11. If the parameter name,data is not passed in, returns the data cache object ret = Thiscache;
return ret;
},//For internal use only.
_data:function (elem, name, data) {return Jquery.data (elem, name, data, true);
},
});
Four. Data (key, value),. Data (Key)
How to use:
$ ("body"). Data ("foo", 52); Incoming key, value
$ ("body"). Data ("Bar", {myType: "Test", count:40});//Incoming key, value
$ ("body"). Data ({baz: [1, 2, 3]} ); Incoming key, value
$ ("body"). Data ("foo");//52//Incoming key
$ ("body"). Data ()//not passed in parameters
HTML5 Data attriubutes:
<div data-role= "page" data-last-value= "data-hidden=" true "data-options= ' {" name ":" John "} ' ></div>
$ ("div"). Data ("role") = = "Page";
$ ("div"). Data ("lastvalue") = =;
$ ("div"). Data ("hidden") = = true;
$ ("div"). Data ("Options"). Name = = "John";
. Data (key, value),. Data (key) source resolution
JQuery.fn.extend ({///1) definition. Data (key, value) Data:function (key) {var parts, attr, name, data = NULL; 2. The condition in which the parameter is not passed in if (typeof key = = "undefined") {if (this.length) {///If the parameter key is undefined, that is, the parameter format is. data (), then the method is called Jquery.da
Ta (elem, name, data, Pvt) Gets the custom data cache object associated with the first matching element and returns.
data = Jquery.data (This[0]);
if (This[0].nodetype = = 1 &&!jquery._data (this[0], "Parsedattrs")) {attr = this[0].attributes;
for (var i = 0, L = attr.length i < l; i++) {name = Attr[i].name;
if (Name.indexof ("data-") = = 0) {name = Jquery.camelcase (name.substring (5));
Dataattr (This[0], name, data[name]);
} jquery._data (This[0], "Parsedattrs", true);
} return data; 3. Parameter key is the case of the object, that is, the parameter format is. Data (key), then iterate through the collection of matching elements, calling method Jquery.data (elem, Name, DATA,PVT) for each matching element to batch set data} else if (typeof key = = "O
Bject ") {return This.each (function () {Jquery.data (this, key);
});
}4.
If only the parameter key is passed in if only the parameter key, or the parameter format is. Data (key), returns the specified name data parts = Key.split (".") of the first matching element; PARTS[1] = parts[1]?
"." + parts[1]: "";
if (value = = = undefined) {data = This.triggerhandler ("GetData" + parts[1] + "!", [parts[0]]); Try to fetch any internally stored data/= undefined && this.length) {data = Jquery.d
ATA (This[0], key);
data = Dataattr (This[0], key, data);
return data = = undefined && parts[1]?
This.data (Parts[0]): data; 5. In the case of the incoming parameter key and value, the parameter format is. data (key, value), set any type of data for each matching element, and trigger the custom event SetData, Changedata} else {return This.each func
tion () {var self = jQuery (this), args = [parts[0], value];
Self.triggerhandler ("SetData" + parts[1] + "!", args);
Jquery.data (this, key, value);
Self.triggerhandler ("Changedata" + parts[1] + "!", args);
}); }, Removedata:function (key) {return This.each (function () {jquery.removedata (this, key);
});
}
}); 6. function dataattr (Elem, key, data) resolves HTML5 attributes data-function dataattr (Elem, key, data) {//If Nothing is found internally, try To fetch any//data from the HTML5 data-* attribute//Only if the parameter data is undefined, the HTML5 property data-if is parsed (data = undefined &A
mp;& Elem.nodetype = = 1) {var name = "data-" + key.replace (Rmultidash, "-$1"). toLowerCase ();
data = Elem.getattribute (name); if (typeof data = = "string") {try {data = data = = "true"? true:data = = = "False"? false:data = = "NULL"? Null:jQuery.isNumeric (data)? parsefloat (data): rbrace.test (data)?
Jquery.parsejson (data): data;
catch (e) {}//Make sure we set the data so it isn ' t changed later Jquery.data (Elem, key, data);
else {data = undefined;
} return data;
}
V. $.removedata (elem, name),. Removedata (Key)
How to use:
$.removedata (Elem, name),. Removedata (key) Source resolution:
$.extend ({//Jquery.removedata (ELEM,NAME,PVT) is used to remove data removedata:function (Elem, Name, PVT/intern) set through Jquery.data ()
Al Use only/* {if (!jquery.acceptdata (Elem)) {return; var thiscache, I, L,//Reference to internal data cache key Internalkey = Jquery.expando, Isnode = ELEM.N Odetype,//Jquery.data for more information cache = Isnode? JQuery.cache:elem,//Jquery.data for more information id = isnode?
elem[Internalkey]: internalkey; If there is already no cache entry to this object, there are no//purpose in continuing if (!cache[ID]) {r
Eturn;
//If pass in the parameter name, remove one or more data if (name) {Thiscache = pvt? cache[ID]: cache[ID].data;
if (Thiscache) {///Only the data cache object Thiscache exists, it is necessary to remove the data//Support array or space separated string names the for data keys if (!jquery.isarray (name)) {//try the string as a key before any manipulation if (name in Thiscache) {Name = [name]; else {//split the camel cased version by spaces unless a key with the spaces exists name = Jquery.camelca
SE (name);
if (name in Thiscache) {name = [name];
else {name = Name.split ("");
(i = 0, L = name.length i < l; i++) {Thiscache) by using operator Delete to remove the data name from the data cache object.
Delete thiscache[Name[i]];
}//If There is no data left in the cache, we want to continue//And let the cache object itself get destroyed
if (! (Pvt. IsEmptyDataObject:jQuery.isEmptyObject) (Thiscache)) {return; }}//Jquery.data for more information//delete custom data cache object Cache[id].data if (!pvt) {delete cache[id]
. data; Don ' t destroy the parent cache unless the internal data object//had been the only thing left in it if (!isempt
Ydataobject (cache[id]) {return; }//Browsers that fail expando deletion also refuse to Delete Expandos on//The window, but it'll allow it on all other JS objects; Other browsers//don ' t care//Ensure that ' cache ' isn't ' a Window object #10080//delete data cache object Cache[id] if (jQuery . Support.deleteexpando | |
!cache.setinterval) {delete cache[id];
else {cache[id] = NULL; //We destroyed the cache and need to eliminate the expando on the node to avoid/false lookups in the cache for Entries that no longer exist//delete the extended Jquery.expando attribute on the DOM element if (Isnode) {//IE does not allow us to delete Expan
Do properties from nodes,//nor does it have a removeattribute function on Document nodes;
We must handle all of these cases if (jQuery.support.deleteExpando) {delete elem[internalkey];
else if (Elem.removeattribute) {elem.removeattribute (Internalkey);
else {elem[Internalkey] = null;
}
}
}
}); JQuery.fn.extend ({removedata:function (key) {return This.each (function () {JqueRy.removedata (this, key);
});
}
}); Checks a cache object for emptiness function isemptydataobject (obj) {to (var name in obj) {//if the public
Data object is empty, the private is still empty if (name = = "Data" && Jquery.isemptyobject (Obj[name)) {
Continue
} if (name!== "Tojson") {return false;
} return true;
}
Vi. $.hasdata (Elem)
How to use: