Data related, data management

Introduction:

$(). Data, used to store object data in the jQuery instance object.

Store and get data through $(). Data.

Code framework:

var data_user, data_priv, rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
rmultiDash = /([A-Z])/g;

function Data() {
}

Data.uid = 1;

Data.accepts = function(owner) {
}

Data.prototype = {
	key: function(){
	},
	set: function(){
	},
	get: function(){
	},
	access: function(){
	},
	remove: function(){
	},
	hasData: function(){
	},
	discard: function(){
	},
}

data_user = new Data();
data_priv = new Data();

jQuery.extend({
	acceptData:  Data.accepts,
	hasData: function(){
	},
	data: function(){
	},
	removeData: function(){
	},
	_data: function(){
	},
	_removeData: function(){
	},
});

jQuery.fn.extend({
	data: function(){
	},
	removeData: function(){
	}
});

function dataAttr(elem, key, data) {
}

The code composition of jQuery and data related functions is roughly the same.

Code resolution:

Variable:

var data_user, data_priv, rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,rmultiDash = /([A-Z])/g;

First, four variables are created, including data_user is A user oriented data storage object_ Priv is the internal data storage object; rbrace is regular, which is used to match any string with any number of characters in braces or brackets; rmultiDash is A regular, which is used to match A single A to Z character.

function Data():

function Data() {
    Object.defineProperty(this.cache = {},
    0, {
        get: function() {
            return {};
        }
    });
    this.expando = jQuery.expando + Math.random();
}

Create constructor for Data, internal this.cache ={}, this empty object.

use Object.defineProperty , making this.cache[0] can only be acquired to get {}, and cannot be assigned.

this.expando = jQuery.expando + Math.random(), jQuery.expando Is an identifier that belongs to a jQuery object. This is equivalent to creating an identity for Data.

Data.uid = 1;

The ID used to represent the node to which the data was added.

 Data.accepts:

Data.accepts = function(owner) {
    return owner.nodeType ? owner.nodeType === 1 || owner.nodeType === 9 : true;
};

A function belongs to a parameter. If the parameter has the attribute nodeType, judge whether the parameter is a node (document or ordinary dom node). If yes, return true. If there is no attribute nodeType, return true directly (this is regarded as an ordinary object). (I don't think it's very rigorous, and the latest version of 3.5.1 has been changed to a new way of judging owner.nodeType === 1 || owner.nodeType === 9 || !(+owner.nodeType) ).

Data.prototype:

Prototype of the Data constructor.

  • key:

key: function(owner) {
	if (!Data.accepts(owner)) {
		return 0;
	}
	var descriptor = {},
	unlock = owner[this.expando];
	if (!unlock) {
		unlock = Data.uid++;
		try {
			descriptor[this.expando] = {
				value: unlock
			};
			Object.defineProperties(owner, descriptor);
		} catch(e) {
			descriptor[this.expando] = unlock;
			jQuery.extend(owner, descriptor);
		}
	}
	if (!this.cache[unlock]) {
		this.cache[unlock] = {};
	}
	return unlock;
},

Function to add an identifier to a new node every time a data is added.

Receive an owner parameter. First, run the Data.accepts(owner) judge that if it is not a DOM node, exit and return 0 directly;

If yes, create an empty descriptor object (the object used to save the Data), and unlock to get the owner's properties this.expando ( this.expando Is the identification string of the Data instance). If the attribute does not exist (Data has not been created yet), start to mount the descriptor object to the owner element node. If it exists, skip it.

If it does not exist, assign the ID of the current data to unlock, and then add one. Then add the attribute to the descriptor, which is named this.expando , the property content is unlock. Then assign the attribute in the descriptor to the owner. (in fact, it is equivalent to adding attributes for the owner this.expando , the content is unlock, and the latest version 3.5.1 has been changed. try catch is given to adapt to different browsers).

Then confirm whether the cache[unlock] exists in the Data instance. If not, initialize it to {}.

Finally, an unlock is returned, indicating the identifier of the node to which the data was added.

  • set:

set: function(owner, data, value) {
	var prop,
	unlock = this.key(owner),
	cache = this.cache[unlock];
	if (typeof data === "string") {
		cache[data] = value;
	} else {
		if (jQuery.isEmptyObject(cache)) {
			jQuery.extend(this.cache[unlock], data);
		} else {
			for (prop in data) {
				cache[prop] = data[prop];
			}
		}
	}
	return cache;
},

Function to add data.

First, create a variable, prop, to act as an attribute for in traversal; unlock, to get the current Data.uid Value; cache, cache= this.cache [unlock], in the array of data stored in the data instance, the data whose subscript is unlock is the data corresponding to the corresponding node.

If the data is a string, add the attribute data in the cache directly, and the attribute content is value.

If it is not a string, judge whether the cache is an empty object. If it is, copy all the data attributes to the cache[unlock]. Otherwise, traverse the data for in and copy the data attributes to the cache.

 

  • get:

get: function(owner, key) {
	var cache = this.cache[this.key(owner)];
	return key === undefined ? cache: cache[key];
},

Enter two parameters, owner and key. The owner represents the data object's attached element, and the key is the corresponding attribute you want to obtain.

First, get the data object corresponding to the p ower. If the attribute exists, get the content of the attribute in the object. Otherwise, return the whole object.

  • access:

access: function(owner, key, value) {
	var stored;
	if (key === undefined || ((key && typeof key === "string") && value === undefined)) {
		stored = this.get(owner, key);
		return stored !== undefined ? stored: this.get(owner, jQuery.camelCase(key));
	}
	this.set(owner, key, value);
	return value !== undefined ? value: key;
},

Function to get or set the data mounted on the node.

Enter three parameters: owner, key and value.

If the key does not exist, or the key exists, but the value does not exist, get the data and i assign the result to the store. If the store exists, the result will be returned. If it does not exist, the key will be converted to the hump and get the data return result again.

If the key exists, use set, add or reset the property, and return value or key

  • remove:

remove: function(owner, key) {
	var i, name, camel, unlock = this.key(owner),
	cache = this.cache[unlock];
	if (key === undefined) {
		this.cache[unlock] = {};
	} else {
		if (jQuery.isArray(key)) {
			name = key.concat(key.map(jQuery.camelCase));
		} else {
			camel = jQuery.camelCase(key);
			if (key in cache) {
				name = [key, camel];
			} else {
				name = camel;
				name = name in cache ? [name] : (name.match(core_rnotwhite) || []);
			}
		}
		i = name.length;
		while (i--) {
			delete cache[name[i]];
		}
	}
},

Used to delete the specified attribute attached to the specified node.

Enter two parameters, owner and key, the element object of data mount, and the attribute name to be deleted.

Create a variable, i, to indicate the number of attributes to be deleted; name, to indicate the array set of attributes to be deleted; camel, to temporarily store the attribute name of humping; unlock, the subscript of the data set corresponding to the node in the cache; cache data set;

First, judge whether the key exists. If not, delete all the corresponding attributes.

If the key exists, judge whether it is an array. If it is an array, directly merge the humped array with the original key, assign it to name, and then delete the attributes one by one.

If it is not an array, judge whether the key exists in the data object. If it exists, hump the key, put it into the array name together with the original key, and then delete the attributes one by one.

If it doesn't exist, determine whether the humped attribute exists. If it exists, assign name as an array with only the humped attribute name string. Otherwise, use regular to match the array or empty array after splitting the space, and then delete the attributes one by one.

  • hasData:

hasData: function(owner) {
    return ! jQuery.isEmptyObject(this.cache[owner[this.expando]] || {});
},

Used to determine whether the node has data attached.

  • discard:

discard: function(owner) {
	if (owner[this.expando]) {
		delete this.cache[owner[this.expando]];
	}
}

Used to delete object data attached to a node.

function dataAttr(elem, key, data):

function dataAttr(elem, key, data) {
	var name;
	if (data === undefined && elem.nodeType === 1) {
		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:
				+ data + "" === data ? +data: rbrace.test(data) ? JSON.parse(data) : data;
			} catch(e) {}
			data_user.set(elem, key, data);
		} else {
			data = undefined;
		}
	}
	return data;
}

Enter three parameters, elem, key, data. Create another variable name internally.

If data does not exist and the attribute nodeType of elem is 1 (dom node), name is assigned to the string'data-', followed by the uppercase letter of key keyword, followed by -, and then converted to a string in lowercase (for example, Aaa is converted to -aaa); data is assigned to the generic content of the attribute name in elem. After data assignment, if it is a string (the value obtained from getAttribute, as long as it exists, will be a string), then assign value to data again according to the string type of data (true string is assigned to true, false string is assigned to false, null string is converted to null, number string is converted to number json string is converted to json object, and other string types remain unchanged). Use data later_ The set method of the user instance object to mount the data object for the element.

If data exists, or elem is not a node, data is assigned undefined.

Finally, data is returned.

jQuery.extend:

Add some data related methods to jQuery.

  • acceptData:

acceptData: Data.accepts,

Directly copy the Data method accept to determine whether the accepted parameter owner is a node.

  • hasData:

hasData: function( elem ) {
	return data_user.hasData( elem ) || data_priv.hasData( elem );
},

Call data_user,data_ As long as there is a data object attached to the node in an instance object, it returns true.

  • data:

data: function( elem, name, data ) {
	return data_user.access( elem, name, data );
},

Using data_ The access method inherited by the user instance is used for data operation.

  • removeData:

removeData: function( elem, name ) {
	data_user.remove( elem, name );
},

Using data_ access method inherited by user instance to remove data.

  • _data:

_data: function( elem, name, data ) {
	return data_priv.access( elem, name, data );
},

Using data_ access method inherited by priv instance to remove data.

  • _removeData:

_data: function( elem, name, data ) {
	data_priv.remove( elem, name );
},

Using data_ access method inherited by priv instance to remove data.

jQuery.fn.extend:

Methods that can be called directly on the jQuery instance.

  • data:

data: function( key, value ) {
	var attrs, name,
		elem = this[ 0 ],
		i = 0,
		data = null;
	if ( key === undefined ) {
		if ( this.length ) {
			data = data_user.get( elem );
			if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
				attrs = elem.attributes;
				for ( ; i < attrs.length; i++ ) {
					name = attrs[ i ].name;
					if ( name.indexOf( "data-" ) === 0 ) {
						name = jQuery.camelCase( name.slice(5) );
						dataAttr( elem, name, data[ name ] );
					}
				}
				data_priv.set( elem, "hasDataAttrs", true );
			}
		}
		return data;
	}
	if ( typeof key === "object" ) {
		return this.each(function() {
			data_user.set( this, key );
		});
	}
	return jQuery.access( this, function( value ) {
		var data,
			camelKey = jQuery.camelCase( key );
		if ( elem && value === undefined ) {
			data = data_user.get( elem, key );
			if ( data !== undefined ) {
				return data;
			}
			data = data_user.get( elem, camelKey );
			if ( data !== undefined ) {
				return data;
			}
			data = dataAttr( elem, camelKey, undefined );
			if ( data !== undefined ) {
				return data;
			}
			return;
		}
		this.each(function() {
			var data = data_user.get( this, camelKey );
			data_user.set( this, camelKey, value );
			if ( key.indexOf("-") !== -1 && data !== undefined ) {
				data_user.set( this, key, value );
			}
		});
	}, null, value, arguments.length > 1, null, true );
},

This is the operation on data in jQuery instance. Enter two parameters key, value.

First, create variables, attrs, the data set representing the attribute of the element; name, the attribute name of the element; elem, the first node element in the jQuery example; i, the number used for traversal in the for loop; data, the data object mounted on the element.

First, judge that if the key keyword does not exist, it means to get all the data. Continue to judge whether there is a length attribute (surface element) in the jQuery instance. If it exists, use data_ The get method of the user instance, which assigns data to the data object mounted on the element.

Continue to judge if the attribute nodeType of elem is 1 (element node) and data_ In the priv instance, if the data object mounted on the element node does not have the hasDataAttrs attribute (indicating that the hasDataAttrs attribute has not been set), assign the attribute array set on the element to attrs, then traverse, assign the attribute name to name, judge, if the attribute name starts with data -, get the data after data -, and hump the attribute name, Add the humped attribute name and content to the attribute object attached to the element, and then, in data_ In the priv instance, add the hasDataAttrs attribute to the data object mounted on the element, and the content is true. Return data.

Case:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>jqueryTest</title>
</head>
<body>
	<div id='one' data-number='one' data-test-number='1'>1</div>
	<script type="text/javascript" src="jquery-2.0.3 formatting.js"></script>
</body>
</html>

If the key keyword exists and is an object, it means that all the data in the object should be copied to the data object mounted on the element. use jQuery.fn.each Function, traverse to realize data_user.set(this, key).

If the keyword exists and is not an object, call jQuery.access (related to jQuery.access Internal execution of), and perform the attribute operation.

Because the input parameters are this (jQuery instance object, save dom element), function (execute function), null, value (passed in parameter value, passed in as parameter again) arguments.length >1 (whether there is value, indicating whether to set property or get property), null, true.

key has been determined not to be an object and must exist. According to the existence of value, there are two execution situations. (i.e jQuery.access Internal implementation)

  1. If value does not exist, arguments.length >If 1 is false, use call to execute the function passed in, point the internal this to the jQuery instance object, and return the execution result.
  2. If value exists, it is equivalent to using call to execute the function passed in, pointing the internal this to the jQuery instance object, and passing in the parameter value. Then return the jQuery instance object.

Finally, the function passed in is parsed: take a parameter value,

There are two situations. One is to call data directly if elem exists and value does not exist_ user.get Function, passing in elem and key to get the relevant attribute values. If it doesn't exist, it will continue to obtain the key by humping. If it doesn't exist, it will copy the attribute value inside the node to the attached data object. If it does, it will continue to obtain. If it does, it will assign a value to data and return data. If it doesn't exist, it will return directly.

If value exists, use data_user.set , set the attribute name as the result of humping, and the attribute value is value; if the result of humping already exists, set the original keyword as the attribute name.

  • removeData:

removeData: function( key ) {
	return this.each(function() {
		data_user.remove( this, key );
	});
}

Each content in the jQuery instance is the attribute of the node, and then data is used_ Remove method of user to remove the specified attribute from the data object.

Tags: Attribute JQuery JSON Javascript

Posted on Sat, 27 Jun 2020 02:34:03 -0400 by PHPdev