Foreword I believe everyone is familiar with jQuery’s data caching. The jQuery caching system is not only used for DOM elements, but also for animations, events, etc. This caching system is used. So in daily practical applications, we often need to cache some data for elements, and these data are often closely related to DOM elements. Since DOM elements (nodes) are also objects, we can directly extend the attributes of DOM elements. However, adding custom attributes and too much data to DOM elements may cause memory leaks, so we should try to avoid doing so. Therefore, a better solution is to use a low-coupling method to connect the DOM and cache data.
In addition: I won’t say much about the introduction and usage of the jQuery.data and jQuery.removeData static methods, as well as the prototype extension methods based on these two methods. You can check the official API documentation.
Implementation ideas jQuery provides a set of flexible and powerful caching methods:
(1) First create a cache object {} inside jQuery to save the cached data . Then extend an attribute with the value expando to the DOM node that needs to be cached, here is "jQuery" (new Date).getTime(). Note: The value of expando is equal to the current time of "jQuery". The possibility of the element itself having this attribute is very small, so the conflict can be ignored.
(2) Then set the value of dom[expando] of each node to an auto-incrementing variable id to maintain global uniqueness. The value of this id is used as the cache key to associate DOM nodes and data. In other words, cache[id] retrieves all caches on this node, that is, id is like the key to opening a room (DOM node). All caches for each element are placed in a map, so that multiple data can be cached at the same time.
(3) So the cache object structure should be like the following:
var cache = {
"uuid1": { // DOM node 1 caches data, "uuid1" is equivalent to dom1[expando]
"name1": value1,
"name2": value2
},
"uuid2": { // DOM node 2 caches data, "uuid2" is equivalent to dom2[expando]
"name1": value1,
"name2": value2
}
// ......
};
Each uuid corresponds to an elem cache data, and each cache object can be composed of multiple name/value (name-value pairs ) pairs, and value can be of any data type.
Simple simulation implementation Based on the above ideas, you can simply implement the functions of jQuery.data and jQuery.removeDate:
(function(window, undefined) {
var cacheData = {}, // Object used to store data
win = window, // Cache window to a variable
uuid = 0,
//Declare a random number (8 digits)
// Note that the random number generated by new Date() is of type Number. After being connected with an empty string (or after being transformed using the toString method), it becomes String, you can use the slice method
expando = "cacheData" ( new Date() "").slice(-8);
// ( new Date()).toString().slice( -8) Equivalent to expando
// write to cache
var data = function(elem, name, value) {
// or use native method to verify string Object.prototype.toString.call( elem) === "[object String]"
// If elem is a string
if (typeof elem === "string") {
// If the name parameter is passed in, it is written Enter cache
if (name !== undefined) {
cacheData[elem] = name;
}
// Return cache data
return cacheData[elem];
// If elem is a DOM node
} else if (typeof elem === "object") {
var id,
thisCache;
// If elem does not have an expando attribute, add an expando attribute (The first time to set a cache for an element), otherwise directly obtain the existing expando and id values
if (!elem[expando]) {
id = elem[expando] = uuid;
thisCache = cacheData [id] = {};
} else {
id = elem[expando];
thisCache = cacheData[id];
}
// Use a random number as the current cache object An attribute of , the cache object can be found using the random number
if (!thisCache[expando]) {
thisCache[expando] = {};
}
if (value !== undefined) {
// Store the data in the cache object
thisCache[expando][name] = value;
}
// Return the data stored in the DOM element
return thisCache[expando ][name];
}
};
// Delete cache
var removeData = function(elem, name) {
// If elem is a string, delete the attribute directly value
if (typeof elem === "string") {
delete cacheData[elem];
// if key is a DOM node
} else if (typeof elem === "object" ) {
// If elem does not have the expando attribute, terminate the execution without deleting the cache
if (!elem[expando]) {
return;
}
// Check whether the object is empty
var isEmptyObject = function(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
removeAttr = function() {
try {
// IE8, the standard browser, can directly use delete to delete attributes
delete elem[expando];
} catch (e) {
// IE6/IE7 uses the removeAttribute method to delete attributes
elem.removeAttribute(expando);
}
},
id = elem[expando];
if (name) {
// Only delete the specified data
delete cacheData[id][expando][name];
// If it is an empty object, all data objects corresponding to the id will be deleted
if (isEmptyObject(cacheData [id][expando])) {
delete cacheData[id];
removeAttr();
}
} else {
// Delete all data stored in the cache for DOM elements
delete cacheData[id];
removeAttr();
}
}
};
// Hang data and removeData under the window global object so that they can be used externally Access these two functions
win.expando = expando;
win.data = data;
win.removeData = removeData;
})(window, undefined);
Example:
HTML structure:
< ;div id="demo" style="height: 100px; width: 100px; background: #ccc; color: #fff; margin: 20px; text-align: center; line-height: 100px;">
demo
For the above example to implement jQuery's simple caching system: first add a randomly generated attribute expando to the DOM element. This attribute is used To store the id value for accessing cached data, it is like the DOM element has a key to open the cache safe. As long as you have the key, you can open the cache safe at any time. The data originally stored in the DOM element is transferred to the cache, and the DOM element itself only needs to store a simple attribute, so that memory leaks caused by the DOM element can be avoided (I don’t know what will happen specifically, everyone knows So~) the risk is minimized.
I am confused at the end. There may be deviations in some terms or explanations. I hope you can correct me and give me some suggestions. In addition, theoretically speaking, , the data and removeData methods can be used for caching any object. However, if used on local objects or window objects, there will be problems such as memory leaks and circular references (^_^ as seen from the Internet), so they are generally used for DOM nodes. More suitable, you can also combine events and animations to cache data on DOM nodes. ps: cache is really important! You need to realize it slowly ~
Because of sharing, it is simple; because of sharing, it is happy.