热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

关于jQuery对象数据缓存Cache原理以及jQuery.data详解

网上有很多教你怎么使用jQuery.data(..)来实现数据缓存,但有两个用户经常使用的data([key],[value])和jQuer

网上有很多教你怎么使用jQuery.data(..)来实现数据缓存,但有两个用户经常使用的data([key],[value])和jQuery.data(element,[key],[value])几乎没有什么文章说清楚它们两的区别,所以我用到了,研究下分享给大家。
$("").data([key],[value])与jQuery.data(element,[key],[value])的区别
这两个函数都是用来在元素上存放数据也就平时所说的数据缓存,都返回jQuery对象,当时我分别在使用它俩的时候真的吓我一跳,区别可大了,真是不用不知道,一用吓一跳。看例子先吧,后再根据源代码分析。

Js代码:

代码如下:

test2

test3

test

aaaa


看了上面的例子是不是发现data([key],[value])与jQuery.data(element,[key],[value])两个根本就不一样了对吧?它们之间到底有没有关系呢。怎么data([key],[value])会覆盖前面key相同的值呢?
而jQuery.data(element,[key],[value])只要是绑定到不同的对象上都不会造成覆盖。是这样吗?那来研究下它们的源代码吧。
先看jQuery.data(element,[key],[value])源代码。

Js代码:

代码如下:

jQuery.extend({
cache: {},

// Please use with caution
uuid: 0,

// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

....
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
// 是否可以附加数据,不可以则直接返回
if ( !jQuery.acceptData( elem ) ) {
return;
}

var privateCache, thisCache, ret,
//jQuery.expando这是一个唯一的字符串,是这介jquery对象产生的时候就生成了。
internalKey = jQuery.expando,
getByName = typeof name === "string",

// 必须区分处理DOM元素和JS对象,因为IE6-7不能垃圾回收对象跨DOM对象和JS对象进行的引用属性
isNode = elem.nodeType,

// 如果是DOM元素,则使用全局的jQuery.cache
// 如果是JS对象,则直接附加到对象上
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,
isEvents = name === "events";

// 避免做更多的不必要工作,当尝试在一个没有任何数据的对象上获取数据时
// 对象没有任何数据,直接返回
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
// id不存在的话就生成一个
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
// 如果是DOM元素则在元素上产生唯一的ID 并且以jQuery.expando
//为属性值为id保存在elem元素上,以便以后再根据jQuery.expando来查找ID。
elem[ internalKey ] = id = ++jQuery.uuid;
} else {
// JS对象则直接使用jQuery.expando,既然是直接附加到对象上,又何必要id呢?
// 避免与其他属性冲突!
id = internalKey;
}
}

//// 当我们试着访问一个键是否含有值的时候,如果不存在jQuery.cache[id]值,
// 初始化jQuery.cache[id]值 为一个空对象{}
if ( !cache[ id ] ) {
cache[ id ] = {};

if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}

// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
// data是接收对象和函数,浅拷贝
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 ];

// 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.
// jQuery内部数据存在一个独立的对象(thisCache.data==thisCache[ internalKey ])
//上,为了避免内部数据和用户定义数据冲突
if ( !pvt ) {
// 存放私有数据的对象不存在,则创建一个{}
if ( !thisCache.data ) {
thisCache.data = {};
}
// 使用私有数据对象替换thisCache
thisCache = thisCache.data;
}
// 如果data不是undefined,表示传入了data参数,则存储data到name属性上
if ( data !== undefined ) {
// jQuery.camelCase( name )作用是如果传入的是object/function,不做转换,
//只有传入的name是字符串才会转换。所以最终保存下来的是key/value对;
thisCache[ jQuery.camelCase( name ) ] = data;
}

//从这以后下面的代码都是处理data: function( elem, name)data为空,求返回值data的情况了。

if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}

// 如果name是字符串,则返回data
// 如果不是,则返回整个存储对象
if ( getByName ) {

// 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;
},
............
});

请看图。

看jQuery.data(element,[key],[value])源代码后可以知道,每一个element都会有自己的一个{key:value}对象保存着数据,所以新建的对象就算有key相同它也不会覆盖原来存在的对象key所对应的value,因为新对象保存是是在另一个{key:value}对象中。

接下来要分析data([key],[value])源代码使用到了each(callback),在分析它之前先看下each(callback)用法和源代码。

Js代码:

代码如下:

test2

test3

test

aaaa




现在来看each方法的具体实现如下:
jQuery.fn = jQuery.prototype = {
each: function( callback, args ) {
return jQuery.each( this, callback, args );
}
}

可以看到它返回的是全局的each方法,并且将自身jQuery对象做为参数给它,全局的each方法的具体实现如下:
// args 作为内部成员的调用来使用
each: function( object, callback, args ) {
var name, i = 0, length = object.length; // 当object为jQuery对象时,length非空

if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i if ( callback.apply( object[ i++ ], args ) === false )
break;
// 以下是客户端程序进行调用
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
// i表示索引值,value表示DOM元素
for ( var value = object[0];
i value = object[++i] ){}
}

return object;
}

现在我们关注下 for ( var value = object[0]; i 得到遍历整个jQuery对象中对应的每个DOM元素,通过callback.call( value,i,value); 将callback的this对象指向value对象,并且传递两个参数,i表示索引值,value表示DOM元素;其中callback是类似于 function(index, elem) { } 的方法。所以就得到 $("").each(function(index, elem){ });

再来看看data([key],[value])的源代码

Js代码:

代码如下:

jQuery.fn.extend({
data: function( key, value ) {
var parts, part, attr, name, l,
elem = this[0],
i = 0,
data = null;

// Gets all values
if ( key === undefined ) {
.....//处理没有Key的情况,这里不是我们要讨论的

return data;
}

// Sets multiple values
if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}

parts = key.split( ".", 2 );
parts[1] = parts[1] ? "." + parts[1] : "";
part = parts[1] + "!";

return jQuery.access( this, function( value ) {

if ( value === undefined ) {
。。。//这里是没有value时,是索取返回值的情况,这不是我们讨论
}

parts[1] = value;

//如果我使用用$("div").data("a","aaa")),下面调用each前的this指的是$("div")这返回的对象,
this.each(function() {//注意了,这里是以每一个匹配的元素作为上下文来执行一个函数
var self = jQuery( this );

self.triggerHandler( "setData" + part, parts );

//这里在元素上存放数据,本质还是委托data(element,[key],[value])来做的。
//看前面有分析过了。
//下面data( this, key, value )里的this指的是遍历整个jQuery对象中对应的每个DOM元素
//$("div")它对应页面中一个
数组。
jQuery.data( this, key, value );//这名句会被循环多次执行,也就是保存数据
//这里就是核心一句话。但要清楚看上面了它是在each(functipn(){})中的。
self.triggerHandler( "changeData" + part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
//在元素上移除存放的数据。具体实现如下:
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
});

如果对于data([key],[value])的源代码不是很了解,好吧,我就用一个例子来模仿实现它吧。

Js代码:

代码如下:

test2

test3

test

aaaa

现在对data([key],[value])与jQuery.data(element,[key],[value])都有了解了吧,如果还是半懂,再回头多看一遍,耐心地理解一下。其实表面上很不一样。但本质上还是有联系的,现在明白原理后就可以请放心地使用了。jQuery.data(element,[key],[value])只把数据绑定到参数element节点上。data([key],[value])
如$("div").data("a","aaaa")它是把数据绑定每一个匹配div节点的元素上。
附加说明下,文中所分析用到的是 jquery-1.7.2.js的源代码。下载地址:http://demo.jb51.net/jslib/jquery/jquery-1.7.2.min.js

 


推荐阅读
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了在Python中检查字符串是否为字母、数字或空白字符的几种方法,包括使用str.isalnum()、str.isalpha()、str.isdigit()和str.isspace()等函数进行判断。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • github上_idea上传本地项目到github上(图解)
    本文由编程笔记#小编为大家整理,主要介绍了idea上传本地项目到github上(图解)相关的知识,希望对你有一定的参考价值。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
author-avatar
mobiledu2502884897
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有