`

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)...

    使用avue-data、dataV、avue搭建的大屏数据展示系统.zip

    本项目利用了三个关键的前端框架——avue-data、dataV和avue,来实现这一目标。这三个组件库各自提供了丰富的功能,使得开发者能够快速高效地构建出交互式、视觉效果出众的数据展示界面。 首先,avue-data是一个...

    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-mongodb-1.8.0.RELEASE(含源码)

    《Spring Data MongoDB 1.8.0.RELEASE:深度解析与源码剖析》 Spring Data MongoDB 是 Spring 框架中的一个模块,专门用于简化与 MongoDB 数据库的交互。MongoDB 是一个流行的分布式文档数据库,以其灵活性和高性能...

    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...

Global site tag (gtag.js) - Google Analytics