.data()
Store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.
根据jquery官网介绍,data给存储DOM关联的数据, 设置数据是对$选取的所有JQuery对象, 获取数据是对$选取的所有对象的第一个对象的存储的数据。
设置语法格式 --- 设置单个数据 .data( key, value ) 设置一组数据 .data( obj ) :
获取语法格式 --- 获取单个数据 .data( key) 设置所有数据 .data() :
例子:
$( "body" ).data( "foo", 52 ); $( "body" ).data( "bar", { myType: "test", count: 40 } ); $( "body" ).data( { baz: [ 1, 2, 3 ] } ); $( "body" ).data( "foo" ); // 52 $( "body" ).data(); // { foo: 52, bar: { myType: "test", count: 40 }, baz: [ 1, 2, 3 ] }
web前端JS编程不可避免地,需要频繁地与DOM对象打交道。 HTML标签负责文档的结构, JS负责文档的行为, CSS负责文档的样式, JS通过document.getElementById()等接口获取DOM对象, 除了操作DOM对象的样式和属性等,往往在行为逻辑上, 脚本需要记录与DOM对象相关的数据 或者 某种状态值, 如果在js中直接使用全局变量记录此值, 具有很大的缺点, 首先不能直观体现此数据与DOM对象的关系, 其次全局变量有可能会发生命名冲突。
例如,一个进度条DOM对象, 需要记录进度百分比值, 可以将此数据使用data接口记录到DOM对象上。
1、 JQuery对象的原型fn函数集合,添加了data接口,此接口判断如果为设置数据, 即arguments.length>1, 表示具有两个参数, 则执行红色代码三行, 将需要设置的DOM对象和需要设置的key和value , 传入 JQuery对象的data接口。
JQuery对象的data接口又做了些什么?
jQuery.fn.extend({
data: function( key, value ) { var i, name, data, elem = this[0], attrs = elem && elem.attributes; ..... return arguments.length > 1 ? // Sets one value this.each(function() { jQuery.data( this, key, value ); }) : // Gets one value // Try to fetch any internally stored data first elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; },
2、 jQuery.data函数分析
调用internalData函数并返回此函数的返回值。
jQuery.extend({ cache: {}, ...... data: function( elem, name, data ) { return internalData( elem, name, data ); },
3、 internalData 函数分析
此函数的第四个入参pvt可以忽略,执行过程有下面几个关键点:
#1 对于DOM对象nodeType为 1, 则缓存cache被设置为JQuery.cache。 此缓存空间即为 每个DOM对象data数据存储空间。
#2 对于第一次使用data接口, 需要对DOM元素, 生成一个唯一的ID: id = deletedIds.pop() || jQuery.guid++;
#3 然后在缓存空间 JQuery.cache中, 按照ID为下表为此DOM元素分配一个子空间: cache[ id ] = {}
#4 将此DOM子空间记录为 thisCache = cache[ id ];
#5 为此DOM子空间再开辟明确的data子空间: thisCache.data = {}; 并将此data子空间记录为thisCache
#6 设置数据 : thisCache[ jQuery.camelCase( name ) ] = data;
function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
............
var ret, thisCache, internalKey = jQuery.expando, // We have to handle DOM nodes and JS objects differently because IE6-7 // can‘t GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // 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 ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; } else { id = internalKey; } } if ( !cache[ id ] ) { // Avoid exposing jQuery metadata on plain JS objects when the object // is serialized using JSON.stringify cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; } ............ 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; } ...............
}
1、此接口判断如果为获取数据, 即arguments.length>1为false, 表示具有一个参数, 则返回 下面函数调用返回的结果: dataAttr( elem, key, jQuery.data( elem, key ) )
dataAttr又做了些什么?
jQuery.fn.extend({
data: function( key, value ) { var i, name, data, elem = this[0], attrs = elem && elem.attributes; ..... return arguments.length > 1 ? // Sets one value this.each(function() { jQuery.data( this, key, value ); }) : // Gets one value // Try to fetch any internally stored data first elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; },
2、 dataAttr 分析
查看注释, 此函数为 data不存在的情况下, 查HTML中 data-开头的相同属性值, 此处可以不用分析。
下面还是分析下下面函数调用执行, jQuery.data( elem, key )
function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) {
3、 jQuery.data( elem, key ) 获取单个数据
调用internalData函数并返回此函数的返回值。
我们下面分析 internalData函数第三个参数 data为空的情况。
jQuery.extend({
cache: {},
......
data: function( elem, name, data ) {
return internalData( elem, name, data );
},
4、 internalData 函数分析
此函数的第四个入参pvt可以忽略:
可以看到,对于获取单个数据情况, 还是从 JQuery.cache[DOM-ID].data中查找, 即下面这一句:
ret = thisCache[ name ];
function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
............... var ret, thisCache, internalKey = jQuery.expando, // We have to handle DOM nodes and JS objects differently because IE6-7 // can‘t GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // 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, // 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;
.................
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; } .................// Check for both converted-to-camel and non-converted data property names // If a data property was specified if ( typeof name === "string" ) { // 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; }
原文:http://www.cnblogs.com/lightsong/p/4020836.html