一.引子
大家想想,在未使用jQuery或者其他js框架前,只用原生js的时候,怎么存储数据的呢?在刚结束js的时候,我是将每个跟节点有关的属性都使用setAttribute(name,value)保存在节点上。下次取就可以直接getAttribute(name),一个节点使用这种方式保存很多数据,效率肯定不高的。在有时候要对节点保存大量的数据的时候,还有没更好的办法来存储数据呢?下面来看看jQuery是如何做的。
二.原理
jQuery数据的存储原理是:
1)定义了一个对象$.cache 保存所有数据
2)对每一个存储数据的DOM节点都对应一个数字index,这个DOM节点下的所有值都存储在$.cache(index)对象中(这么看是不是觉得$.cache是一个数组? 其实js中数组和对象很像,数组也是对象,对象就是一组属性的集合)。
3)对每一个存储数据的DOM节点都生成一个唯一的index。这个index值保存在节点的expando属性中。
4)expando是什么?就是每一个jQuery框架加载的时候内部生成的一个随机序列。这个序列一个jQuery加载完只有唯一一个。
让图片来更清楚的描述:
调用$(“#test”).data(“name”)时会先找到对象属性jQuery17102199497243038011($.expando)的值(当前为1),这个值就1就是上面说的index。对象所有存储的值都是放在$.cache[“1”]对象中。
下面代码可验证:
$("#test").data("abc", "def");
var cacheIndex = document.getElementById("test")[$.expando]; //获取index
//$.expando在1.2版本里访问不到,不能
var obj = $.cache[cacheIndex];
alert(obj["abc"]); //def 注:这是jQuery1.6 前取值方式
//注: 在jquery1.7版本中对存储值有所改变。需要obj[“data”]["abc"]才能取到。也就是说$(“#test”).data(“abc”,”def”)不是存在上述obj对象中,而是存在obj[“data”]对象中(多了一层data对象,变得更深了)。
三.源码
下面来看代码是如何做到的:
jQuery.fn.extend({
//扩展jQuery的对象方法data
data: function( key, value ) {
var parts, attr, name,data = null;
//如果key没有,执行的操作
if ( typeof key === "undefined" ) {
if ( this.length ) {
/**获取对象数组第一个元素的数据缓存cache
* (该对象包含当前元素的所有存储的数据)
*/
data = jQuery.data( this[0] );
//元素节点
if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
attr = this[0].attributes;
for ( var i = 0, l = attr.length; i < l; i++ ) {
name = attr[i].name;
if ( name.indexOf( "data-" ) === 0 ) {
name = jQuery.camelCase( name.substring(5) );
dataAttr( this[0], name, data[ name ] );
}
}
jQuery._data( this[0], "parsedAttrs", true );
}
}
return data;
} else if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}
parts = key.split(".");
parts[1] = parts[1] ? "." + parts[1] : "";
//.data(name)格式,取值
if ( value === undefined ) {
data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
// Try to fetch any internally stored data first
if ( data === undefined && this.length ) {
data = jQuery.data( this[0], key );
data = dataAttr( this[0], key, data );
}
return data === undefined && parts[1] ?
this.data( parts[0] ) :
data;
//.data(name, value)格式,设置值
} else {
return this.each(function() {
var self = jQuery( this ),
args = [ parts[0], value ];
//触发事件,如果对节点设置值绑定了事件,在做操作时触发事件
self.triggerHandler( "setData" + parts[1] + "!", args );
jQuery.data( this, key, value );
self.triggerHandler( "changeData" + parts[1] + "!", args );
});
}
}
});
下面是静态方法:
jQuery.extend({
/** jQuery静态方法,算是data的核心了
* jQuery很多都是这种模式,在静态方法里定义一个核心的处理方法
* 在对象方法中定义用户操作的接口,就是API。
* 如事件:$("#id").click(),$("xx").hover()等等。
* 但最终处理都是调$("#id").on() 到最后是$.event.add()方法
*/
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
//判断当前节点能不能存储数据
if ( !jQuery.acceptData( elem ) ) {
return;
}
var privateCache, thisCache, ret,
internalKey = jQuery.expando,
getByName = typeof name === "string",
/**判断元素是否是DOM对象,如果是DOM对象才使用全局cache,普通js对象,直接增加属性即可.
* DOM对象可以直接增加属性,为什么这个非得用全局对象呢?
* 这主要是解决IE6-7浏览器垃圾回收对于js创建的DOM对象的属性不能回收
* 验证方法:(使用sIEve 可看到有内存泄露)
* function A() {
* var a = document.createElement("div");
* a["b"] = function(){};
* document.getElementById("test").appendChild(a);
* a.parentNode.removeChild(a);
* }
* A();
*/
isNode = elem.nodeType,
cache = isNode ? jQuery.cache : elem,
//获取index
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
isEvents = name === "events";
// Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
if ( !id ) {
//为每一个存储数据在全局cache中的DOM节点分配一个唯一index
if ( isNode ) {
elem[ internalKey ] = id = ++jQuery.uuid;
} else {
id = internalKey;
}
}
if ( !cache[ id ] ) {
cache[ id ] = {};
// Avoids exposing jQuery metadata on plain JS objects when the object
// is serialized using JSON.stringify
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}
//如果name是对象或函数,继承里面所有方法.注意:这边为什么判断pvt ?
if ( typeof name === "object" || typeof name === "function" ) {
if ( pvt ) {
cache[ id ] = jQuery.extend( cache[ id ], name );
} else {
cache[ id ].data = jQuery.extend( cache[ id ].data, name );
}
}
privateCache = thisCache = cache[ id ];
//要知道pvt是jQuery自己内部使用的,将保存用户和jQuery内部数据的保存分开了。
//将我们设置的name/value值
//放在了cache[id].data对象中,而jQuery内部数据直接放在了cache[id]中
//好处不言而喻,将用户和jQuery框架的数据分开保存,避免了名称冲突
//1.7版本之后才区分开.上面例子已经说了
if ( !pvt ) {
if ( !thisCache.data ) {
thisCache.data = {};
}
thisCache = thisCache.data;
}
//存储数据
if ( data !== undefined ) {
thisCache[ jQuery.camelCase( name ) ] = data;
}
// Users should not attempt to inspect the internal events object using jQuery.data,
// it is undocumented and subject to change. But does anyone listen? No.
if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}
if ( getByName ) {
ret = thisCache[ name ];
if ( ret == null ) {
ret = thisCache[ jQuery.camelCase( name ) ];
}
} else {
ret = thisCache;
}
return ret;
}
});
本章结束,有不对和不准确的地方望大家指正。有疑问欢迎留言。
- 大小: 33.3 KB
分享到:
相关推荐
实现的功能:对电商评论数据的采集、清洗、存储、分析与可视化。 ### 1.项目介绍 本系统基于Hadoop平台,使用Maven进行项目管理,基于ssm框架开发的项目,使用mysql数据库,前端采用JQuery+Bootstrap+ECharts展示...
软件开发设计:PHP、QT、...云计算与大数据:数据集、包括云计算平台、大数据分析、人工智能、机器学习等,云计算是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需提供给计算机和其他设备。
基于Java电商评论数据的分析与可视化系统源码+部署说明.zip 1、该资源内项目代码都是经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化...
读取Kafka消息队列的实时流数据,并与mysql进行集成,将读取到的数据储存到MySQL数据库当中,通过编写java程序读取MySQL中的数据和编写Web数据处理程序将数据传至前端,最后利用echart、jQuery等技术,实现实时新闻...
2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...
│ │ 13.RPC底层通讯原理之Netty线程模型源码分析.wmv │ │ │ ├─14.分库分表之后分布式下如何保证ID全局唯一性 │ │ 14.分库分表之后分布式下如何保证ID全局唯一性.mp4 │ │ │ └─15.大型公司面试必答之...
本项目用的是spring tool suite + maven的集成...分析功能运用大数据里面的数据挖掘和数据抽取技术,先采集到数据,然后对数据排序处理过后,能看到数据销量排行,就能得到数据:哪些商品销售量大,哪些商品的销售量
千锋python基础教程:1、第一个python程序与数据存储 '千锋python基础教程:2、print&input;与变量和运算符' 千锋python基础教程:3、字符串与循环中的while '千锋python基础教程:4、布尔&list;与条件循环语句与...
数据库设计:该项目使用MySQL数据库进行数据存储,主要包括以下几个表:用户表(user):存储用户的基本信息;员工表(employee):存储员工的基本信息;考勤记录表(attendance):存储员工的考勤记录;部门表...
**ASP.NET某店POS积分管理系统 - 销售情况与...数据库:采用SQL Server存储业务数据,确保数据的安全性和稳定性。 本系统不仅适用于毕业设计,还可直接应用于实际零售业务中,帮助商家提升管理水平,增强市场竞争力。
该应用程序使用Java语言开发,采用Android Studio作为开发环境,使用MySQL数据库进行数据存储和管理。同时,该应用程序还使用了Bootstrap框架和jQuery库,使得界面更加美观和易用。 部署说明: 1. 下载源码文件并...
2. 智能仓储优化:利用大数据分析算法,实时监控仓库内货物的存储情况和流动情况,提供最优的货物存放和取出方案,降低了运输成本和空间利用率。3. 实时监控和预警:通过传感器和监控摄像头实时监测仓库内的环境和...
> - 数据存储技术:Dataframe文件存储 > > - 深度学习框架:keras > > - 前端技术:bootstrap4+jquery+ajax+echats > > - 算法:lstm,归一化 **项目结构** ![img](image/clip_image001.png) **结构说明** > - ...
5、增加“高意向客户”菜单,该模块存储你所有高意向客户,通过该功能对客户进行分类,便于进行漏斗式管理。 6、给客户添加跟进后,客户状态改为“已跟进”同时客户排列在列表顶部,解决“已跟进”和“未跟进”客户...
此外,我们还采用了安全性的最佳实践,如输入验证、安全过滤和加密存储等,以保护用户数据的安全性。 我们的项目源码具有良好的可读性和可维护性,采用了面向对象的设计原则和模式。我们使用了MVC(Model-View-...
【技术分析】 ... CSS,可以帮助把网页外观做得更加美观; JavaScript,是一种轻量级的解释...数据安全:对用户数据进行加密存储、访问控制等措施,保护用户隐私和系统安全。 日志功能:记录关键操作日志,保留操作痕迹。
数据统计:对明星应援活动的数据进行统计和分析,以便了解粉丝的支持情况。 通过以上技术和功能的结合,weixin114明星应援系统为粉丝提供了一个便捷、高效的应援平台,同时也为系统管理员提供了方便的管理工具。
【技术分析】 ... CSS,可以帮助把网页外观做得更加美观; JavaScript,是一种轻量级的解释...数据安全:对用户数据进行加密存储、访问控制等措施,保护用户隐私和系统安全。 日志功能:记录关键操作日志,保留操作痕迹。
2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...
【技术分析】 ... CSS,可以帮助把网页外观做得更加美观; JavaScript,是一种轻量级的解释...数据安全:对用户数据进行加密存储、访问控制等措施,保护用户隐私和系统安全。 日志功能:记录关键操作日志,保留操作痕迹。