`

Data源码

 
阅读更多

实现功能:

为文档元素、节点元素、普通对象以this.expando为键添加Data对象,对外接口获取、设置、移除该Data对象,以及判断该Data对象是否有值;

Data对象分为共有和私有两种,共有的Data对象提供外部接口获取和设置该Data对象的内容,私有的Data对象直接在内部调用构建或获取Data对象的方法,(event模块的回调函数队列通过私有的Data对象构建);

节点元素提供便捷的获取、设置、移除方法,元素的data起始的属性快速合并到Data对象中,通过$.fn.extend方法实现。

 

源码:

data模块外部接口实现,提供$.data|removeData|hasData|_data|_removeData方法,(后两个方法将弃用,其他模块中构建私有data直接调用dataPriv模块),以及$ele.data|removeData方法,对节点元素进行快速操作。

define([
	"./core",
	"./core/access",
	"./data/var/dataPriv",// 创建私有的Data对象
	"./data/var/dataUser"// 创建共有的Data对象
],function(jQuery,access,dataPriv,dataUser){

"use strict";

var rbrace=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,// {}或[]包裹
	rmultiDash=/[A-Z]/g;

// data不等于undefined时,获取data
// data等于undefined时,获取元素elem的data-key属性,并为elem创建Data对象,获取data
function dataAttr(elem,key,data ){
	var name;

	if ( data===undefined && elem.nodeType===1 ){
		name="data-" + key.replace(rmultiDash,"-$&").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){}

			dataUser.set(elem,key,data);// 为elem元素创建Data对象
		}else{
			data=undefined;
		}
	}
	return data;
}

jQuery.extend({
	// 判断elem对象(普通对象、元素或文档节点对象),是否有Data对象属性,以this.expando为键
	hasData:function(elem){
		return dataUser.hasData(elem) || dataPriv.hasData(elem);
	},

	// 设置或获取elem的共有Data对象
	data:function(elem,name,data){
		return dataUser.access(elem,name,data);
	},

	// 移除elem的共有Data对象下割属性,或者清空该内存单元
	removeData: function(elem,name){
		dataUser.remove(elem,name);
	},

	// 私有Data对象构建,为达成其私有性,改由模块中直接调用dataPriv函数
	_data:function(elem,name,data){
		return dataPriv.access(elem,name,data);
	},

	_removeData:function(elem,name){
		dataPriv.remove(elem,name);
	}
});

jQuery.fn.extend({
	data:function(key,value){
		var i, name, data,
			elem=this[0],
			attrs=elem && elem.attributes;

		if ( key===undefined ){
			if ( this.length ){
				data=dataUser.get(elem);// 共有Data对象设置值

				if ( elem.nodeType===1 && !dataPriv.get(elem,"hasDataAttrs") ){
					i=attrs.length;
					while ( i-- ){

						// Support: IE 11 only
						// The attrs elements can be null (#14894)
						if ( attrs[i] ){
							name=attrs[i].name;
							if ( name.indexOf("data-")===0 ){
								name=jQuery.camelCase(name.slice(5));

								// 获取elem下Data对象的属性
								// 或者获取元素的data-name属性,并设置elem下Data对象的属性
								dataAttr(elem,name,data[name]);
							}
						}
					}
					// 当元素的data-name属性再度得到修改时,私有Data对象hasDataAttrs为真
					// 怎样将元素的data-name属性下数据并入共有Data对象??
					dataPriv.set(elem,"hasDataAttrs",true);
				}
			}

			return data;
		}

		if ( typeof key==="object" ){
			return this.each( function(){
				dataUser.set(this,key);
			});
		}

		// data模块中使用access函数,以elem、value为参数执行fn函数,获取或设置Data对象
		return access(this,function(value){
			var data;

			if ( elem && value===undefined ){

				data=dataUser.get(elem,key);
				if ( data!==undefined ){
					return data;
				}

				data=dataAttr(elem,key);
				if ( data!==undefined ){
					return data;
				}

				return;
			}

			this.each(function(){
				dataUser.set(this,key,value);
			});
		},null,value,arguments.length>1,null,true);
	},

	// elem下共有Data对象移除属性,或清空内存
	removeData:function(key){
		return this.each( function(){
			dataUser.remove(this,key);
		});
	}
});

return jQuery;
});

 

只能接受元素节点、文档节点和普通对象,用以在该对象下构建新的Data对象。

define(function(){

"use strict";

// 判断参数owner是否可接受,接受元素节点、文档节点、普通对象,可接受时创建Data对象
return function(owner){

	// Accepts only:
	//  - Node
	//    - Node.ELEMENT_NODE
	//    - Node.DOCUMENT_NODE
	//  - Object
	//    - Any
	return owner.nodeType===1 || owner.nodeType===9 || !(+owner.nodeType);
};
});

 

私有Data对象。

define([
	"../Data"// 提供Data对象的方法,最终Data对象附着在原始对象的属性中,从而可配置
],function( Data ){
	"use strict";

	return new Data();// 创建Data对象
});

 

共有Data对象。

define([
	"../Data"
], function( Data ) {
	"use strict";

	return new Data();
});

 

以this.expando为键创建Data对象,通常只能通过方法获取或设置Data对象。

cache方法获取Data对象,或者在参数是节点元素、文档元素、普通对象的前提下,创建Data对象;set方法以双参数字符串形式或单参数对象形式设置Data对象;get方法获取Data对象或其属性;access方法首参key为undefined或次参value为undefined时,获取Data对象或其属性,否则为设置Data对象下的属性值,返回key或value;remove方法移除Data对象相应的key键(可为数组),当该Data对象为空时清除内存;hasData方法判断Data对象存在且不为空对象。

define([
	"../core",
	"../var/rnotwhite",// 非空白字符
	"./var/acceptData"// 判断参数owner是否可接受,接受元素节点、文档节点、非节点对象
], function(jQuery,rnotwhite,acceptData){

"use strict";

function Data(){
	this.expando=jQuery.expando+Data.uid++;
}

Data.uid=1;

Data.prototype={

	// 判断owner是否可接受Data设置的对象,可接受时以this.expando创建空对象,或者获取this.expando属性
	cache:function(owner){// event模块中使用owner参数为元素jquery对象

		var value=owner[this.expando];// 获取缓存

		if ( !value ){
			value={};

			// We can accept data for non-element nodes in modern browsers,
			// but we should not, see #8335.
			// Always return an empty object.
			if ( acceptData(owner) ){// 判断参数owner是否可接受,接受元素节点、文档节点、非节点对象

				if ( owner.nodeType ){// 节点jquery对象设置this.expando属性为空对象
					owner[this.expando]=value;

				}else{// 其他对象同样设置this.expando属性为空对象,且可配置
					Object.defineProperty(owner,this.expando,{
						value:value,
						configurable:true
					});
				}
			}
		}

		return value;
	},

	// 设置owner[this.expando]对象的属性,双参数字符串形式或单参数对象形式
	set:function(owner,data,value){
		var prop,
			cache=this.cache(owner);

		if ( typeof data==="string" ){
			cache[jQuery.camelCase(data)]=value;
		}else{
			for ( prop in data ){
				cache[jQuery.camelCase(prop)]=data[prop];
			}
		}
		return cache;
	},

	// 获取owner[this.expando]对象或其属性
	get:function(owner,key){
		return key===undefined ? this.cache(owner) : 
			owner[this.expando] && owner[this.expando][jQuery.camelCase(key)];
	},

	// key为undefined时为获取owner[this.expando],否则为设置,返回value或key
	access:function(owner,key,value){
		// 获取
		if ( key===undefined || ( (key && typeof key==="string") && value===undefined ) ){
			return this.get(owner,key);
		}

		// 设置
		this.set(owner,key,value);

		return value!==undefined ? value : key;
	},

	// 移除owner[this.expando]的key属性(可为数组),owner[this.expando]为空时清除内存
	remove:function(owner,key){
		var i,
			cache=owner[this.expando];

		if ( cache===undefined ){
			return;
		}

		if ( key!==undefined ){

			if ( jQuery.isArray(key) ){

				key=key.map(jQuery.camelCase);
			}else{
				key=jQuery.camelCase(key);

				key=key in cache ? [key] : ( key.match(rnotwhite) || [] );
			}

			i=key.length;

			while ( i-- ){
				delete cache[key[i]];
			}
		}

		if ( key===undefined || jQuery.isEmptyObject(cache) ){
			if ( owner.nodeType ){
				owner[this.expando]=undefined;
			}else{
				delete owner[this.expando];
			}
		}
	},

	// 判断owner[this.expando]对象是否存在
	hasData:function(owner){
		var cache=owner[this.expando];
		return cache!==undefined && !jQuery.isEmptyObject(cache);
	}
};

return Data;
});

 

0
0
分享到:
评论

相关推荐

    mysql.data源码

    MySQL.Data是.NET Framework用于连接和操作MySQL数据库的第三方组件,主要由Oracle公司提供。这个组件使得.NET开发者能够方便地在他们的应用程序中集成MySQL数据库的功能,而无需深入理解MySQL的底层通信协议。在...

    spring-data源码

    通过对Spring Data Elasticsearch 2.1.10.RELEASE的源码分析,我们可以深入了解其工作原理,从而更好地利用这一工具。 首先,Spring Data Elasticsearch的核心理念是提供一个统一的编程模型,让开发者能以声明式的...

    c++ lib-pcap-data 源码以及文档

    标题中的“c++ lib-pcap-data 源码以及文档”指的是一个关于C++编程语言与libpcap数据包捕获库的相关资源集合。libpcap是一个开源的库,广泛用于网络数据包分析和捕获,它在各种操作系统上都有支持,包括Linux和...

    spring data实战源码

    《Spring Data实战源码》是基于Spring Data框架的一本深入解析书籍,其随书源码提供了丰富的示例和实践案例,帮助读者理解Spring Data的核心概念和技术。Spring Data是一个强大的库,旨在简化数据库访问并增强数据...

    CoCoa Data 源码学习

    本源码学习资源包含16个章节,旨在帮助开发者深入理解并有效利用Cocoa Data来优化其程序。下面我们将详细探讨Cocoa Data的主要概念、工作流程以及这些章节可能涵盖的关键知识点。 1. **对象图管理**: Cocoa Data的...

    易语言data源码,易语言data1源码,易语言数据库查看

    在易语言中,"data"通常指的是数据处理和存储,而"数据库查看"则涉及到如何访问、操作和显示数据库中的信息。在易语言中,对数据库的操作主要包括连接数据库、执行SQL语句、获取查询结果并展示等步骤。 首先,我们...

    spring-data-应用源码

    这个"spring-data-应用源码"包含了一些示例项目,可以帮助我们深入了解如何在实际应用中使用 Spring Data。 首先,让我们关注 Spring Data JPA。JPA(Java Persistence API)是 Java 平台上的对象关系映射(ORM)...

    DataMatrix动态库源码

    DataMatrix动态库源码是一种用于生成DataMatrix二维条形码的软件开发资源,它由C++语言编写,方便开发者在自己的应用程序中集成DataMatrix码的生成功能。DataMatrix码是一种广泛应用在工业自动化、物流管理、电子...

    Qt Data Visualization 源码包

    这个源码包,名为"qtdatavis3d-opensource-src-5.7.0-beta",提供了Qt Data Visualization模块的源代码,用于深入理解和自定义这个库的功能。 在5.7.0版本的Beta版中,你可以期待一些前沿的特性以及开发者可能正在...

    qt data visualization 5.7.1 源码

    在安装QT Data Visualization源码时,你需要配置CMake,设置QT的安装路径和其他必要的编译变量,然后让CMake生成适用于你操作系统的构建文件。之后,使用Make或类似工具进行编译和链接。 在编程接口(API)方面,QT...

    Core Data 示例源码 操作xml归档

    这个“Core Data 示例源码 操作xml归档”是一个示例项目,旨在演示如何在OS X平台上利用Core Data框架来处理XML档案。通过这个教程,我们可以深入理解Core Data与XML数据持久化之间的交互。 首先,Core Data是一个...

    spring data jpa 实例源码

    spring data jpa 实例源码 spring data jpa 实例源码 spring data jpa 实例源码

    Spring Data Commons 源码

    Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。Commons - 提供共享的基础框架,适合各个子...

    C# DataMatrix.net 源码

    《C# DataMatrix.net 源码解析与应用实践》 C# DataMatrix.net 是一个专为.NET平台设计的库,用于生成和读取DataMatrix条形码。DataMatrix是一种二维条形码标准,通常用于在小空间内存储大量数据,如电子元件制造、...

    Spring Data JPA Examples 官方源码

    这个"Spring Data JPA Examples"官方源码提供了丰富的示例,帮助开发者深入理解如何在实际项目中应用Spring Data JPA。 1. **Spring Data JPA基础** Spring Data JPA通过提供一套高级的Repository接口,使得开发者...

    Spring-data + MongoDb源码

    在IT领域,Spring Data是一个广泛使用的框架,它简化了与各种数据存储的交互,包括关系型数据库、NoSQL数据库和搜索引擎。MongoDB则是一种流行的NoSQL文档型数据库,以其灵活性、可扩展性和高性能而受到赞誉。Spring...

    生意参谋data解密PHP源码

    生意参谋data解密PHP源码,AES解密,7C04B0CCE6699A80D9A670C7697472A37AAA0C4F147D1CFFED9038A7E5E8AC9DB2D13C58E5096694E899E73E8261F3344F489FE1E05DC81FA6668CABE25FAC19724391C000FBD214933E07B6D6FA3E701ADEF...

    spring data jpa 源码

    JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合ORM技术

Global site tag (gtag.js) - Google Analytics