JQuery data cache module history details _ jquery

Source: Internet
Author: User
The data cache system was first introduced by jQuery1.2, when its event system was copied to the addEvent of DE. js, and addEvent has a defect in implementation. It puts the Event Callback above EventTarget, which will lead to the introduction of the circular reference data cache system jQuery1.2 at the earliest, at that time, its Event System copied the addEvent of DE. js, and addEvent has a defect in implementation. It puts the Event Callback above EventTarget, which will lead to circular reference. If EventTarget is a window object, it will cause global pollution. With the data cache system, in addition to avoiding these two risks, we can also effectively save the intermediate variables produced by different methods, which will be useful to the methods of another module, dependencies between decoupling methods. For jQuery, its event cloning and subsequent queuing implementation are inseparable from the cache system.

JQuery1.2 adds two static methods in the core module: data and removeData. Data needless to say, like other jQuery methods, it combines read and write. JQuery's cache system places all data above $. cache, and then assigns a UUID to each element node that uses the cache system. The UUID property name is a random custom property, "jQuery" + (new Date (). getTime (). The value is an integer and increases progressively from zero. However, the UUID is always attached to an object. If the object is a window, isn't it a global pollution? Therefore, when jQuery internally determines that it is a window object, it is mapped to an empty object called windowData, add the UUID to it. With UUID, when we access the cache system for the first time, an empty object (cache body) will be opened in the $. cache object for storing things related to the target object. This is a bit like opening a bank account. The UUID value is the passbook. RemoveData will be deleted and no longer need to save the data. If the data is cleared at the end, it does not have any key-value pairs and becomes an empty object, jQuery will start from $. delete this object from the cache and remove the UUID from the target object.

The Code is as follows:


// JQuery1.2.3
Var expando = "jQuery" + (new Date (). getTime (), uuid = 0, windowData = {};
JQuery. extend ({
Cache :{},
Data: function (elem, name, data ){
Elem = window? WindowData: elem; // special processing of window objects
Var id = elem [expando];
If (! Id) // if there is no UUID, a new one is created.
Id = elem [expando] = ++ uuid;
// If you have not opened an account in $. cache, open an account first.
If (name &&! JQuery. cache [id])
JQuery. cache [id] = {};

// When the third parameter is not undefined, It is a write operation.
If (data! = Undefined)
JQuery. cache [id] [name] = data;
// If there is only one parameter, the cache object is returned. If there are two parameters, the target data is returned.
Return name? JQuery. cache [id] [name]: id;
},

RemoveData: function (elem, name ){
Elem = window? WindowData: elem;
Var id = elem [expando];
If (name) {// remove the target data
If (jQuery. cache [id]) {
Delete jQuery. cache [id] [name];
Name = "";

For (name in jQuery. cache [id])
Break;
// Traverse the cache body. If it is not empty, the name will be rewritten. If it is not rewritten, then! Name is true,
// This method is called again, but only one parameter is passed this time to remove the cache body,
If (! Name)
JQuery. removeData (elem );
}
} Else {
// Remove UUID, but an error will be thrown when delete is used for the element in IE.
Try {
Delete elem [expando];
} Catch (e ){
If (elem. removeAttribute)
Elem. removeAttribute (expando );
} // Cancel the account
Delete jQuery. cache [id];
}
}
})



JQuery adds two prototype Methods data and removeData with the same name in 1.2.3 to facilitate chain and set operations. Add the trigger logic of custom events of getData and setData to data.

1.3, the data cache system is finally independent into a module data. js (Division during internal development), and added two sets of Methods: queue and dequeue in the namespace, and queue and dequeue in the prototype. The purpose of queue is to cache a group of data and serve the animation module. Dequeue deletes one from a group of data.

The Code is as follows:


// JQuery1.3
JQuery. extend ({
Queue: function (elem, type, data ){
If (elem ){
Type = (type | "fx") + "queue ";
Var q = jQuery. data (elem, type );
If (! Q | jQuery. isArray (data) // ensure that an array is stored.
Q = jQuery. data (elem, type, jQuery. makeArray (data ));
Else if (data) // then add something to the data
Q. push (data );
}
Return q;
},
Dequeue: function (elem, type ){
Var queue = jQuery. queue (elem, type ),
Fn = queue. shift (); // then delete one. In the early stage, it was the callback for placing the animation. Delete it and call it,
// But no determination on whether the function is used. It is estimated that it is not written in the document and used internally.
If (! Type | type = "fx ")
Fn = queue [0];
If (fn! = Undefined)
Fn. call (elem );
}
})



Example of calling the animate method of the fx module:

The Code is as follows:


// Each processes multiple animations in parallel, while queue processes multiple animations one by one.
This [optall. queue === false? "Each": "queue"] (function () {/* omitted */})


Adding custom attributes to an element also raises a problem. If we copy this element, this attribute will also be copied. As a result, both elements have the same UUID value and data is operated incorrectly. JQuery's early replication node implementation is very simple. If the element's cloneNode method does not copy the event, it uses cloneNode; otherwise, it uses the element's outerHTML or the parent node's innerHTML, use the clean method to parse a new element. However, both outerHTML and innerHTML are explicitly written in the attribute, so you need to clear them with regular expressions.

The Code is as follows:


// JQuery1.3.2 core. js clone method
Var ret = this. map (function (){
If (! JQuery. support. noCloneEvent &&! JQuery. isXMLDoc (this )){
Var html = this. outerHTML;
If (! Html ){
Var p = this. ownerDocument. createElement ("p ");
P. appendChild (this. cloneNode (true ));
Html = p. innerHTML;
}
  
Return jQuery. clean ([html. replace (/jQuery \ d + = "(? : \ D + | null) "/g," "). replace (/^ \ s */," ")]) [0];
} Else
Return this. cloneNode (true );
});


JQuery1.4 found that IE may throw an error if there are three old labels for accessing external resources: object, ember, and applet. Since the element nodes of legacy IE are only packaged by COM, once resources are introduced, they will become instances of that type of resources, and they will have strict access control, users cannot add members as they are in common JS objects. Therefore, jQuery changes the data, but none of the three tags will cache data for it. JQuery gets a hash called noData, which is used to detect the labels of element nodes.

The Code is as follows:


NoData: {"embed": true,
"Object": true,
"Applet": true },
// Code defense
If (elem. nodeName & jQuery. noData [elem. nodeName. toLowerCase ()]) {
Return;
}


JQuery1.4 also improved $. data, allowing the second parameter to be an object, so as to facilitate the storage of multiple data. The custom property expando corresponding to the UUID is also placed under the namespace. The queue and dequeue methods are separated into a new module.
JQuery1.43 brings three improvements.
First, add the changeData custom method. However, this method has no sales volume, but it is the narcissism of the product manager.
Check whether the logic of adding custom attributes to an element node is independent into an acceptData method. Because the jQuery team found that when the flash resource loaded by the object tag can still add custom attributes, it decided to open the Internet in this case. When loading flash, IE needs to specify an attribute named classId for the object, the value is clsid: D27CDB6E-AE6D-11cf-96B8-444553540000, so the detection logic becomes very complex, because data, removeData are used, standalone effectively saves bits.
HTML5 responds to user-defined attributes and adds a cache mechanism called "data. When the attributes you set start with "data-", they are saved to the dataset object of the element node. This may lead to the convenience of using HTML5 to cache data, or the use of jQuery's cache system to save data, so the data method becomes useless. Therefore, jQuery enhances the data on the prototype. When you access this element node for the first time, it traverses all the Custom Attributes starting with "data-" (to take care of the old IE, can not directly traverse dataset), put them in the cache body of jQuery. When a user obtains data, the user first accesses the "data-" custom attribute from the cache system without using setAttribute. But the HTML5 cache system is very weak and can only store strings (this is of course due to the consideration of circular references), so jQuery will restore them to various data types, such as "null ",, "false", "true" is changed to null, false, true. strings in the numeric format are converted to numbers, if it ends with "{" starting with "}", it is converted into an object.

The Code is as follows:


// JQuery1.43 $. fn. data
Rbrace =/^ (? : \ {. * \} | \ [. * \]) $ /;
If (data === undefined & this. length ){
Data = jQuery. data (this [0], key );
If (data = undefined & this [0]. nodeType = 1 ){
Data = this [0]. getAttribute ("data-" + key );
  
If (typeof data = "string "){
Try {
Data = "true "? True:
Data = "false "? False:
Data = "null "? Null:
! JQuery. isNaN (data )? ParseFloat (data ):
Rbrace. test (data )? JQuery. parseJSON (data ):
Data;
} Catch (e ){}
  
} Else {
Data = undefined;
}
}
}

JQuery1.5 also brings three improvements. At that time, jQuery had defeated Prototype. js in 1.42, such as Sunday, Matthew effect, and a surge in users. It focuses on improving performance and entering the fix bug stage (more users, the more free testers, the larger the test coverage ).
Improved expando, which was originally based on the time cut. Now it is the version number plus a random number. Therefore, you may introduce multiple versions of jQuery on one page.
Whether the logic of this data is extracted into a hasData method, and the "data-*" attribute for processing HTML5 is also extracted into a private method dataAttr. They are all for a clearer logic. DataAttr uses JSON. parse, because this JSON may be introduced by JSON2.js, and JSON2.js has a very bad thing: It adds the toJSON method to a series of native types, an error occurred while determining whether the for in object is null. JQuery was forced to implement an isEmptyDataObject method for processing.
JQuery's data cache system was originally differentiated for event system services. Later on, it was the infrastructure of many internal modules. In other words, it stores many framework users' variables (System Data) internally, but once it is published to the document, users will also use data to save the data they use in their business (user data ). In the past, there was a small user base, and there was little possibility of variable name conflicts. In addition, jQuery picked some uncommon names for these system data, __class __, _ change _ or add a suffix or something. No complaints were received. When jQuery becomes a world-class framework, the user data name takes down the system data name, resulting in paralysis of the Event System or other modules. JQuery began to transform the cache body. It turned out to be an object and all the data was thrown in it. Now it opens up a sub-object in the cache, with the key name random jQuery. expando value. If it is system data, it will be stored in it. However, for the sake of forward compatibility, the events system data is directly placed on the cache body. As for how to distinguish between system data, it is very simple to add the fourth parameter directly in the data method, and the true value is the system data. The third parameter is also provided when removeData is used to delete system data. A _ data method is also created for operating system data. The following figure shows the structure of the cache body:
 

The Code is as follows:

 
Var cache = {
JQuery14312343254: {/* place System Data */}
Events: {/"put event name and its corresponding callback list "/}
/* Place user data here */
}


JQuery1.7 improves the cache body and changes the system variables to the data object. Therefore, we need to make improvements to determine that the cache body is empty. Now we need to skip toJSON and data. The new structure is as follows:

The Code is as follows:


Var cache = {
Data: {/* place user data */}
/* Place system data here */
}


JQuery1.8 added an array named deleteIds to reuse UUID, but it was a flash. The UUID value starts from 1.8 and does not use jQuery. uuid. Instead, it is generated incrementally using jQuery. guid. After jQuery1.83, the implementation of Operation data is extracted as private methods. The namespace and prototype methods are only a proxy and are divided into two groups to operate the data of user data, removeData: _ data, _ removeData of the operating system data. Now the cache system is a huge family.

In the end, data cache establishes a one-to-one relationship between the target object and the cache body, and then operates data on the cache body. The complexity is concentrated in the former. It is never difficult to add, delete, modify, and query a property in a common JS object, and users cannot perform any tricks. From the software design principle, this is also the best result (consistent with the KISS Principle and single responsibility ).
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.