jQuery.access源码分析
基本理解
jQuery.attr是jQuery.attr,jQuery.prop,jQuery.css提供底层支持,jQuery里一个比较有特色的地方就是函数的重载, 比如attr,有如下几种重载
- $('#box').attr('title')
- $('#box').attr('title','标题')
- $('#box').attr({title:'标题',data-menu-toggle:'dropdown'})
- $('#box').attr('title',function () {....})
但是纵观jQuery.attr代码中,却没有判断value是不是存在啊之类的,ok,你猜对了,在access里实现了
jQuery.fn.extend({
attr: function (name, value) {
return jQuery.access(this, jQuery.attr, name, value, arguments.length > 1);
},
removeAttr: function (name) {
return this.each(function () {
jQuery.removeAttr(this, name);
});
},
prop: function (name, value) {
return jQuery.access(this, jQuery.prop, name, value, arguments.length > 1);
}
});
源码分析
大致思路
- 1.首先判断key值是不是一个object,如果是,遍历key,递归调用jQuery.access,并将是否可以链式调用的标志位设置为true
- 2.判断value值是否已经定义,如果已经定义,说明是个set操作
- 2.1 set操作的是可链式调用的
- 2.2 如果value不是function,设置raw为true
- 2.3 判断key值是否为null或者undefined,key若为空值
- 2.3.1 如果value不是个函数,或者强制赋值raw为true,那么调用fn,可能是以下调用:$('#box').attr(null,{abc:'def',a:'1'})
- 2.3.1 如果value是个函数,将fn包装之,改变原来fn的作用域和参数
- 2.4 如果fn存在,遍历jQuery内部元素,分别执行set操作
- 3.首先判断是否为set方法,如果是,返回 elems,如果不是执行get操作(如果jQuery内部length为0,返回指定的默认空值)
源码
// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
/**
attr: function (name, value) {
return jQuery.access(this, jQuery.attr, name, value, arguments.length > 1);
},
*
* @param elems jQuery的this
* @param fn 函数
* @param key 属性
* @param value 值
* @param chainable 是否可以链式调用,如果是get动作,为false,如果是set动作,为true
* @param emptyGet 如果jQuery没有选中到元素的返回值
* @param raw value是否为原始数据,如果raw是true,说明value是原始数据,如果是false,说明raw是个函数
* @returns {*}
*/
access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
var i = 0,
length = elems.length,
bulk = key == null; // bulk 体积,容量;大多数,大部分;大块 // Sets many values
/**
* 如果参数key是对象,表示要设置多个属性,则遍历参数key,遍历调用access方法
*
* $('#box').attr({data:1,def:'addd'});
*/
if ( jQuery.type( key ) === "object" ) {
chainable = true; //表示可以链式调用
for ( i in key ) {
jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
} // Sets one value /**
* $('#box').attr('customvalue','abc')
* $('#box').attr('customvalue',function (value) {});
*/ } else if ( value !== undefined ) {
chainable = true; if ( !jQuery.isFunction( value ) ) {
raw = true;
} if ( bulk ) { // if (key == null && value !== undefined)
// Bulk operations run against the entire set
/**
* $('#box').attr(undefined,'abc')
*
* jQuery.attr.call(elems,value); 调用完毕之后,将fn设置为空
*/
if ( raw ) {
fn.call( elems, value );
fn = null; // ...except when executing function values
/**
* $('#box').attr(undefined,function () {})
*
* fn = bulk = jQuery.attr;
*
* fn = function (elem, key, value) {
* return jQuery.attr.call(jQuery(elem),value);
* }
*
*/
} else { //如果key有值的话,好办,这里的bulk是为了节省一个变量,将fn用bulk存起来,然后封装fn的调用
bulk = fn;
fn = function( elem, key, value ) {
return bulk.call( jQuery( elem ), value );
};
}
} //jQuery.access(elems,jQuery.attr,) //如果fn存在,掉调用每一个元素,无论key是否有值,都会走到这个判断,执行set动作
if ( fn ) { // 递归调用之
for ( ; i < length; i++ ) {
fn( elems[i], key,
raw ? value :
/**
* 如果value是原始数据,就取value,如果是个函数,就调用这个函数取值
* $('#box').attr('abc',function (index,value) { index指向当前元素的索引,value指向oldValue
*
* 先调用jQuery.attr(elements[i],key) 取到当前的值,然后调用传入的fn值
* });
*/ value.call( elems[i], i, fn( elems[i], key ) )
);
}
}
} /**
* 如果chainable为true,说明是个set方法,就返回elems
* 否则说明是get方法
* 1.如果bulk是个true,说明没有key值,调用fn,将elems传进去
* 2.如果bulk为false,说明key有值哦,然后判断元素的长度是否大于0
* 2.1 如果大于0,调用fn,传入elems[0]和key,完成get
* 2.2 如果为0,说明传参有问题,返回指定的空值emptyGet
*/
return chainable ?
elems : // Gets
bulk ?
fn.call( elems ) :
length ? fn( elems[0], key ) : emptyGet;
},
ExtJS 中的flexSetter方法
这让我猛然想起了Ext的flexSetter方法,该方法在Ext.Function.flexSetter 详细API请看这里
用法:
var ele = document.getElementById('box');
function setAttribute(name, value) {
ele.setAttribute(name, value);
}
var flexSetAttribute = Ext.Function.flexSetter(setAttribute);
flexSetAttribute('title', '标题');
flexSetAttribute({
'abc': 'otherattribu',
'other': 1
});
源码
/**
* 1.关于Ext.enumerables的实现
*
* 这里为了兼容某些浏览器的toString,valueOf等内置方法不能被遍历出来的bug
* var o = {toString:111,valueOf:222};
*
* for (var oo in o)
* {
alert(oo);
}
*
*/
var enumerables = [//'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
'valueOf', 'toLocaleString', 'toString', 'constructor']; for (i in { toString: 1 }) {
enumerables = null;
} Ext.Function = {
flexSetter: function(setter) {
return function(name, value) { // 返回一个闭包
var k, i; if (name !== null) {
if (typeof name !== 'string') { //如果name不是字符串,这里就认为是对象,进行for in
for (k in name) {
if (name.hasOwnProperty(k)) {
setter.call(this, k, name[k]); //逐个调用setter
}
} if (Ext.enumerables) {
for (i = Ext.enumerables.length; i--;) {
k = Ext.enumerables[i];
if (name.hasOwnProperty(k)) {
setter.call(this, k, name[k]);
}
}
}
} else {
setter.call(this, name, value); // 如果是个字符串,直接调用了
}
} return this;
};
}
};
总结:很显然,Ext的flexSetter没有jQuery的强大,但是足够严谨,jQuery.access为prop、attr等上层需要灵活设置参数的功能做了一个统一的整理,方便了调用,节省了比特。
jQuery.access源码分析的更多相关文章
- jQuery.attributes源码分析(attr/prop/val/class)
回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和p ...
- jQuery.queue源码分析
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong ) 队列是一种特殊的线性表,它的特殊之处在于他只允许在头部进行删除,在尾部进行插入.常用来表示先进先出的操作(FI ...
- jQuery.buildFragment源码分析以及在构造jQuery对象的作用
这个方法在jQuery源码中比较靠后的位置出现,主要用于两处.1是构造jQuery对象的时候使用 2.是为DOM操作提供底层支持,这也就是为什么先学习它的原因.之前的随笔已经分析过jQuery的构造函 ...
- jQuery.Deferred 源码分析
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong ) 1 引子 观察者模式是我们日常开发中经常用的模式.这个模式由两个主要部分组成:发布者和观察者.通过观察者模式, ...
- jQuery 2.0.3 源码分析 钩子机制 - 属性操作
jQuery提供了一些快捷函数来对dom对象的属性进行存取操作. 这一部分还是比较简单的. 根据API这章主要是分解5个方法 .attr() 获取匹配的元素集合中的第一个元素的属性的值 或 设置 ...
- jQuery 2.1.4版本的源码分析
jQuery 2.1.4版本的源码分析 jquery中获取元素的源码分析 jQuery.each({// 获取当前元素的父级元素 parent: function(elem) { var parent ...
- jQuery.Callbacks 源码解读二
一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...
- jQuery 源码分析(十二) 数据操作模块 html特性 详解
jQuery的属性操作模块总共有4个部分,本篇说一下第1个部分:HTML特性部分,html特性部分是对原生方法getAttribute()和setAttribute()的封装,用于修改DOM元素的特性 ...
- jQuery 源码分析(十三) 数据操作模块 DOM属性 详解
jQuery的属性操作模块总共有4个部分,本篇说一下第2个部分:DOM属性部分,用于修改DOM元素的属性的(属性和特性是不一样的,一般将property翻译为属性,attribute翻译为特性) DO ...
随机推荐
- (原)ubuntu16在torch中使用caffe训练好的模型
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5783006.html 之前使用的是torch,由于其他人在caffe上面预训练了inception模型 ...
- android 利用重力感应监听 来电时翻转手机后静音。
在CallNotifier.java中 加入如下代码: public void GetSensorManager(Context context) { sm = (SensorManager) ...
- Mysql表大小数据大小索引大小查询
SELECT CONCAT(ROUND((INDEX_LENGTH+DATA_LENGTH)/1024/1024, 2), 'MB') AS '总大小',CONCAT(ROUND(DATA_LENGT ...
- JavaScript权威指南阅读笔记3
第六章 对象 1.首先是先介绍了对象直接量的格式:对象直接量就是1.由若干个名/值对组成的映射表,2名/值对中间由冒号分割,3名值对之间由逗号分割,4整个映射表由花括号括起来.这样就组成了一个对象直接 ...
- linux下挂载CDROM命令
cdrom装载在/dev/cdrom 下面. 挂载时在权限范围内建立一个文件夹.例如mkdir /home/dang/cdtmp 然后执行 mount dev/cdrom /home/dang/cdt ...
- py正则表达式
1.元字符 . ^ $ * + ? {} [] \ | () --> [] : - 常用来指定一个字符集:[abc], [a-z] 匹配任意一个字符 - 元字符在字符集中不起作用:[akm ...
- Knight Moves(BFS,走’日‘字)
Knight Moves Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- ZOJ 3745 Salary Increasing
Description Edward has established a company with n staffs. He is such a kind man that he did Q time ...
- linux下源码安装apache服务
1.搭建静态网站是,我们只需要搭建apache服务即可满足要求. 例如:如果我再客户端游览器输入地址,他会找到192.168.1.100这个服务器,然后根据端口会找到apache服务器.apache他 ...
- jQuery中$符号冲突问题 (转载)
Jquery的$命名冲突: 在Jquery中,$是JQuery的别名,所有使用$的地方也都可以使用JQuery来替换,如$('#msg')等同于JQuery('#msg') 的写法.然而,当我们引入多 ...