jquery源码解析:jQuery数据缓存机制详解2
上一课主要讲了jQuery中的缓存机制Data构造方法的源码解析,这一课主要讲jQuery是如何利用Data对象实现有关缓存机制的静态方法和实例方法的。我们接下来,来看这几个静态方法和实例方法的源码解析:
data_user = new Data(); //对外使用的数据缓存对象
data_priv = new Data(); //内部的数据缓存对象,内部使用
jQuery.extend({ //在jQuery中添加静态方法
acceptData: Data.accepts, //调用Data构造函数的accepts静态方法
hasData: function( elem ) { //是否有这个属性
return data_user.hasData( elem ) || data_priv.hasData( elem );
},
data: function( elem, name, data ) {
return data_user.access( elem, name, data );
},
removeData: function( elem, name ) {
data_user.remove( elem, name );
},
_data: function( elem, name, data ) { //_代表私有的方法,不对外
return data_priv.access( elem, name, data );
},
_removeData: function( elem, name ) {
data_priv.remove( elem, name );
}
});
静态方法,是直接调用Data原型上的方法,而上一课已经详细讲解了这个Data的原型,可以参照上一课。而在jQuery缓存系统中,我们经常使用的就是以下这几个实例方法:
jQuery.fn.extend({ //在jQuery原型上添加实例方法
data: function( key, value ) { //一个参数时是获取数据,两个参数时是设置数据
var attrs, name,
elem = this[ 0 ], //找到一组元素中的第一个,如果是获取操作,只获取一个元素,如果是设置,就设置这一组元素
i = 0,
data = null;
if ( key === undefined ) { //当不传入参数时,就代表取这个元素的所有数据,比如:$("div").data();
if ( this.length ) { //如果有元素
data = data_user.get( elem ); //获取这个元素的数据
//下面这一段代码是来处理HTML5中的自定义属性data-xxx的。比如:<div id="div1" data-chao-ji="dan"></div>,$("#div1")[0].dataset.chaoJi等于"dan"(HTML5写法)。$("#div1").data("chaoJi")等于"dan"。jQuery缓存系统会把HTML5自定义属性data-xxx这种格式的数据自动缓存起来。
if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {//元素是否是Element,元素是否有hasDataAttrs属性,第一次是没有的,也就是undefined。data_priv是内部使用的Data对象,不会影响到外部使用的Data对象data_user。
attrs = elem.attributes; //获取元素所有的属性
for ( ; i < attrs.length; i++ ) {
name = attrs[ i ].name; //得到每一个属性的名字
if ( name.indexOf( "data-" ) === 0 ) { //如果元素中的属性名有data-开头的字符串,就进入到if语句
name = jQuery.camelCase( name.slice(5) ); //取data-后面的字符串,也就是chao-ji,然后转驼峰格式,也就是变成chaoJi。
dataAttr( elem, name, data[ name ] ); //把data-开头的属性名的值添加到缓存系统中
}
}
data_priv.set( elem, "hasDataAttrs", true ); //设置此元素的hasDataAttrs属性值为true
}
}
return data;
}
if ( typeof key === "object" ) { //比如:$("#div1").data({name:"chaojidan",age:"25"});
return this.each(function() { //对每个元素,都在数据缓存中设置json中的属性值
data_user.set( this, key );
});
}
return jQuery.access( this, function( value ) { //access的第一个参数是所有元素,第二个参数是回调,第三个参数是key值,第四个参数是value值。第五个参数的作用是来决定回调是用来设置数据还是获取数据的(true代表设置操作,false代表获取操作)。第六个参数和第七个参数是内部使用的,我们不用管。
var data,
camelKey = jQuery.camelCase( key );
if ( elem && value === undefined ) { //如果value为空的话,就代表参数只有一个,那么arguments。length=1 >1,返回false,因此代表获取操作,获取元素elem在缓存系统中的key属性值
data = data_user.get( elem, key ); //获取数据
if ( data !== undefined ) { //如果找到,就直接返回
return data;
}
data = data_user.get( elem, camelKey ); //如果没找到,就再找key的驼峰方式的属性值,比如:$("#div1").data("name-age"),它会先找name-age这种属性名的值,如果没找到,就找nameAge这种属性名的值。
if ( data !== undefined ) {
return data;
}
data = dataAttr( elem, camelKey, undefined ); //如果都没找到,就找HTML5自定义属性data-xxx的值,比如:元素div上的data-name-age的属性值。
if ( data !== undefined ) {
return data;
}
return;
}
this.each(function() { //如果value存在,就代表是设置操作。就循环所有元素,对每个元素都设置
var data = data_user.get( this, camelKey ); //先去缓存系统中取key的驼峰形式的属性值
data_user.set( this, camelKey, value ); //然后把值设置给key的驼峰形式的属性名
if ( key.indexOf("-") !== -1 && data !== undefined ) { //如果key包含"-",并且之前取到的key的驼峰形式的属性值存在,那么就把此驼峰形式的属性值,赋给key这个属性名。举个例子:$("#div1").data("name-age","1"),这时缓存系统中会存储nameAge:1,然后我再$("#div1").data("name-age","2"),这时data = 1,nameAge:2,进入if语句,缓存系统会再存储name-age:1。
data_user.set( this, key, value );
}
});
}, null, value, arguments.length > 1, null, true );
},
removeData: function( key ) { //删除数据
return this.each(function() {
data_user.remove( this, key );
});
}
});
function dataAttr( elem, key, data ) { //key=chaoJi
var name;
if ( data === undefined && elem.nodeType === 1 ) { //首先判断数据缓存中是否有此名字的属性值,如果没有,并且元素是Element,就进入if语句。如果数据缓存中已经有了此名字的属性值,那么就直接返回这个值。意思就是:当HTML5的data-xxx的属性名xxx与jQuery通过data方法添加到数据缓存的属性名xxx是一样的,那么你通过data方法访问时,获取到的值是数据缓存中的xxx属性值,而不是HTML5的data-xxx的属性值,只有数据缓存没有这个xxx的属性值时,才会去取HTML5的data-xxx的属性值。
name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); //rmultiDash = /([A-Z])/g;取大写字母,也就是J,然后用-J代替J,这时key是chao-Ji,然后转小写,因此变成chao-ji。name= "data-chao-ji"
data = elem.getAttribute( name ); //得到元素上的这个HTML5自定义属性的属性值"dan"
if ( typeof data === "string" ) { //如果属性值是字符串就保存到缓存系统
try {
data = data === "true" ? true :
data === "false" ? false :
data === "null" ? null :
+data + "" === data ? +data : //如果是数字字符串,就存入数字
rbrace.test( data ) ? JSON.parse( data ) : //rbrace判断是否是一个json字符串,如果是就解析成json。
data; //如果是字符串,就直接返回字符串
} catch( e ) {}
data_user.set( elem, key, data );
} else { //如果不是字符串就直接返回undefined,也就是说HTML5的data-xxx的属性值只能是一个字符串,如果不是,那么你通过jQuery的data(xxx)方法获取时,是获取不到的,返回undefined。
data = undefined;
}
}
return data;
}
缓存系统到此结束,下一课将讲解队列Queue的实现原理。
大家不要以为这就是源码粘贴,其实里面的注释是非常重要的,有些复杂的,我都会举例子说明,因此看起来不会很难。请看里面的注释。
加油!
jquery源码解析:jQuery数据缓存机制详解2的更多相关文章
- jQuery 源码分析(十) 数据缓存模块 data详解
jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...
- jquery源码解析:jQuery数据缓存机制详解1
jQuery中有三种添加数据的方法,$().attr(),$().prop(),$().data().但是前面两种是用来在元素上添加属性值的,只适合少量的数据,比如:title,class,name等 ...
- jQuery 源码分析(十八) ready事件详解
ready事件是当DOM文档树加载完成后执行一个函数(不包含图片,css等),因此它的触发要早于load事件.用法: $(document).ready(fun) ;fun是一个函数,这样当DOM树加 ...
- jQuery 源码分析(十一) 队列模块 Queue详解
队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...
- gulp源码解析(一)—— Stream详解
作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() ...
- 10.Spark Streaming源码分析:Receiver数据接收全过程详解
原创文章,转载请注明:转载自 听风居士博客(http://www.cnblogs.com/zhouyf/) 在上一篇中介绍了Receiver的整体架构和设计原理,本篇内容主要介绍Receiver在 ...
- jQuery源码04 data() : 数据缓存
/* Implementation Summary 1. Enforce API surface and semantic compatibility with 1.9.x branch 2. Imp ...
- Linux源码解析-内核栈与thread_info结构详解
1.什么是进程的内核栈? 在内核态(比如应用进程执行系统调用)时,进程运行需要自己的堆栈信息(不是原用户空间中的栈),而是使用内核空间中的栈,这个栈就是进程的内核栈 2.进程的内核栈在计算机中是如何描 ...
- Spring源码解析--IOC根容器Beanfactory详解
BeanFactory和FactoryBean的联系和区别 BeanFactory是整个Spring容器的根容器,里面描述了在所有的子类或子接口当中对容器的处理原则和职责,包括生命周期的一些约定. F ...
随机推荐
- 清华镜像站安装docker
https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/
- BaseAnimation是基于开源的APP,致力于收集各种动画效果(最新版本1.3) (转)
声明:部分动画来源于网络,本人只是想方便收集在一起,如果不妥请及时与我联系!谢谢 为了统一BaseAnimationApp签名,一定要方便以后大家自动更新...防止签名冲突,不能及时更新 1.3源码下 ...
- token的作用及实现原理
1:首先,先了解一下request和session的区别request 指在一次请求的全过程中有效,即从http请求到服务器处理结束,返回响应的整个过程,存放在HttpServletRequest对象 ...
- linux下,MySQL默认的数据文档存储目录为/var/lib/mysql。
0.说明 Linux下更改yum默认安装的mysql路径datadir. linux下,MySQL默认的数据文档存储目录为/var/lib/mysql. 假如要把MySQL目录移到/home/data ...
- struts,hibernate,spring配置时问题汇总及解决办法
1.java.lang.NoClassDefFoundError: org/objectweb/asm/ClassVisitor 缺少asm-3.3.jar 2.java.lang.NoClassDe ...
- HDU1232 畅通工程 2017-04-12 19:20 53人阅读 评论(0) 收藏
畅通工程 Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submissi ...
- B-spline Curves 学习之B样条曲线的系数计算与B样条曲线特例(6)
B-spline Curves: Computing the Coefficients 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关 ...
- 好用的开关按钮——switchbutton
1.简介 GitHub地址:https://github.com/zcweng/SwitchButton gradle: repositories { mavenCentral() jcenter( ...
- Homework 4
Homework 4 开发工具:dev c++ 开发语言:c++ 源代码上传至github:上传一直失败... 合作人:曹权 博客地址:http://www.cnblogs.com/c2016/ 这里 ...
- md1
a b link to baidu 我不懂啊 这是什么意思 http://example.com/ 这里是一段代码' adsfasdf 你 你输得算好了 反正就这样吧,大概也值能这样了注 我想写一段引 ...