jQuery的XX如何实现?——3.data与cache机制
往期回顾:
--------------------------
源码链接:内附实例代码
jQuery使用许久了,但是有一些API的实现实在想不通。于是抽空看了jQuery源码,现在把学习过程中发现的一些彩蛋介绍给大家(⊙0⊙)。
下面将使用简化的代码来介绍,主要关注jQuery的实现思想~>_<~
相较于第一篇(与第二篇无相关性),代码更新了:27~71
(function(window, undefined) {
function jQuery(sel) {
return new jQuery.prototype.init(sel);
}
jQuery.prototype = {
constructor: jQuery,
init: function(sel) {
if(typeof sel === 'string'){
var that = this;
var nodeList = document.querySelectorAll(sel);
Array.prototype.forEach.call(nodeList, function(val, i){
that[i] = val;
})
this.selector = sel;
this.length = nodeList.length;
}
}
}
jQuery.prototype.init.prototype = jQuery.prototype;
window.$ = jQuery;
function Data() {
this.uid = 1;
//原来是防篡改对象(简化一下)
this.cache = {};
this.expando = 'jQuery' + Math.random();
}
Data.prototype = {
//获取elem的uid值
key: function(elem) {
var uid = elem[this.expando];
if(!uid) {
//为elem分配一个uid
uid = this.uid++;
elem[this.expando] = uid;
}
if(!this.cache[uid]) {
this.cache[uid] = {};
}
return uid;
},
set: function(elem, name, val) {
var cache = this.cache[this.key(elem)];
cache[name] = val;
},
get: function(elem, name) {
var cache = this.cache[this.key(elem)];
return cache[name];
}
}
var data_user = new Data();
jQuery.prototype.data = function(name, val) {
if(val) {
Array.prototype.forEach.call(this, function(elem) {
data_user.set(elem, name, val);
})
return this;
}
else return data_user.get(this[0], name);
}
})(window);
--------------------------
cache在jQuery中的作用:为dom分配一个存储空间。简而言之,就是为了保存数据(⊙0⊙),比如:
1.data API 2.事件队列
下面结合图片与代码来介绍cache与dom之间是如何建立联系的。

在图中可以看到,elem下有一个{jQueryXXX : cache.uid}的键值对。通过elem[Data.expando]可以获取到这个elem在Data下的cache.uid。有了cache.uid后,我们就可以取到elem在Data.cache中的数据。
有点绕,我们用伪代码整理一下:
var uid = elem[Data.expando];
var data = Data.cache[uid];
最后获取到的data就是elem在Data.cache中保存的数据╰( ̄▽ ̄)╮
--------------------------
好了,有了上面的思路,我们现在用js代码实现出来。
先介绍Data.prototype下的三个方法,有了这三个方法,后续的操作都会非常简便╰( ̄▽ ̄)╮
Data.prototype.key(获取elem的uid):
1.获取elem在Data.cache中的uid【38行】;
2.为新的elem在Data.cache中建立一个新的空间【39~47行】,并返回uid;
key: function(elem) {
var uid = elem[this.expando];
if(!uid) {
//为elem分配一个uid
uid = this.uid++;
elem[this.expando] = uid;
}
if(!this.cache[uid]) {
this.cache[uid] = {};
}
return uid;
}
Data.prototype.set(保存数据):
set: function(elem, name, val) {
var cache = this.cache[this.key(elem)];
cache[name] = val;
}
Data.prototype.get(读取数据):
get: function(elem, name) {
var cache = this.cache[this.key(elem)];
return cache[name];
}
三个函数实现完毕后,其实针对cache的操作就非常简便了。保存数据就调用set,读取数据就调用get。
--------------------------
接下来,利用cache机制来实现data API。
//保存数据
$('#div').data('key1', 123);
//读取数据
$('#div').data('key1');
实现起来也非常简便,所以直接上代码,各位客官自己琢磨下了~>_<~+
代码的第66行就是保存数据,而第70行就是读取数据。
var data_user = new Data();
jQuery.prototype.data = function(name, val) {
if(val) {
Array.prototype.forEach.call(this, function(elem) {
data_user.set(elem, name, val);
})
return this;
}
else return data_user.get(this[0], name);
}
最后,运行如代码:
$('#div').data("num", 123);
$('#div').data("objVal", {val:123});
console.log($('#div').data("num"));
console.log($('#div').data("objVal"));
得到结果:

--------------------------
最后再唠叨几句:这里实现data API是非常简陋的~>_<~+。实际中:
1.jQuery会对data的name进行格式限制(比如data-*);
2.还能识别dom上的数据(比如<div data-haha="123"></div>);
3.elem被remove掉的时候,还会删除对应cache上的数据;
jQuery的XX如何实现?——3.data与cache机制的更多相关文章
- jQuery的XX如何实现?——4.类型检查
往期回顾: jQuery的XX如何实现?——1.框架 jQuery的XX如何实现?——2.show与链式调用 jQuery的XX如何实现?——3.data与cache机制 -------------- ...
- jQuery的XX如何实现?——2.show与链式调用
往期回顾: jQuery的XX如何实现?——1.框架 -------------------------- 源码链接:内附实例代码 jQuery使用许久了,但是有一些API的实现实在想不通.于是抽空看 ...
- jQuery的XX如何实现?——1.框架
源码链接:内附实例代码 jQuery使用许久了,但是有一些API的实现实在想不通.于是抽空看了jQuery源码,现在把学习过程中发现的一些彩蛋介绍给大家(⊙0⊙). 下面将使用简化的代码来介绍,主要关 ...
- jquery在元素中存储数据:data()
转自:http://www.php.cn/js-tutorial-405445.html 在元素中存储数据:data() 1 2 3 4 5 6 7 8 9 10 <!DOCTYPE html& ...
- org.springframework.data.redis.cache.RedisCacheManager
org.springframework.data.redis.cache.RedisCacheManager
- 判断和调整library cache,data dictionary cache,buffer cache性能
Oracle SGA是oracle的内存结构,存放着oracle通过oracle进程读写的内存数据.sga分为好多组件,比如shared pool,buffer cache,redo log buff ...
- jQuery中attr()、prop()、data()用法及区别
.attr(),此方法从jq1.0开始一直存在,官方文档写的作用是读/写DOM的attribute值,其实1.6之前有时候是attribute,有时候又是property..prop(),此方法jq1 ...
- jquery方法详解--bind(type, [data], fn)
转自:http://www.zhufengpeixun.cn/jquery/bind_type_data_fn.html bind(type, [data], fn) 返回值::jQuery 概述 ...
- jquery中attr、prop、data
在高版本的jquery中获取标签的属性,可以使用attr().prop().data(),那么这些方法有什么区别呢? 对于HTML元素本身就带有的固有属性,在处理时,使用prop方法. 对于HTML元 ...
随机推荐
- C语言 malloc calloc realloc alloc 在分配内存时的 区别
malloc : 向堆申请分配内存,不初始化 calloc : 向堆申请分配内存,初始化为0 realloc: 向堆申请分配内存,可调整大小 alloc : 向栈申请内存,不需手动释放
- poj 2337 有向图输出欧拉路径
Catenyms Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10186 Accepted: 2650 Descrip ...
- Ruby-打包程序
1.下载 ocra-1.3.1.gem 文件 2.打开“start Command prompt with ruby” 命令窗口 3.输入 “gem install e:\ocra-1.3.1.ge ...
- 各种 starter poms (启动器)
starter包含了搭建项目,快速运行所需的依赖.它是一个依赖关系描述符的集合.当应用需要一种spring的服务时,不需要粘贴拷贝大量的依赖关系描述符.例如想在spring中使用redis,只需要在项 ...
- VS调试在Win7(vista系列)操作系统下 HttpListener拒绝访问解决办法
一. VS调试在Win7(vista系列)操作系统下 HttpListener无法绑定多个 指定IP.端口问题 来自:http://www.cnblogs.com/ryhan/p/4195693.ht ...
- 《CSS3秘籍》(第三版)-读书笔记(3)
第9章 装饰网站导航 1. 选择要定义样式的链接 大部分浏览器都支持4种基本的链接状态:未访问的链接.已访问的链接.访问者的鼠标正悬停在上方的链接,以及正被单击的链接.CSS提供了与这些状态对应的4 ...
- 启用 mvc webapi 的 session功能可用
默认 mvc webapi 不开启 session 会话支持 所以需要修改配置,在 Global 开启 session 支持 如下: 1.重写 init() 方法 public override vo ...
- mac下sublime text3安装SFTP及使用
mac下sublime text3安装SFTP 1.shift+command+p进入控制面板 2.输入install进入程序安装界面选择需要安装的插件(SFTP) 3.直接进行安装(需要联网) 4. ...
- php session的存放目录,再次回顾
session的存放位置可以通过运行时配置ini_set和函数session_save_path来设置 .session_save_path - 读取/设置当前会话的保存路径 string sessi ...
- 【网站运营】网站被K的原因大总结
对于广大的站长来说网站被K或者是被降权是经常有的事情,不过我基本上还没有看见过Google的K站情况,也就是给网站降个权什么的处罚.如果你是用了很严重的作弊手段的话,那指定会是被Google给K掉的. ...