jQuery属性操作之.attr()
转载请注明出处
@[toc]
# .attr()
1.**.attr()**的四种用法
大致用法:
- 调用形式:$("xxx").attr(attrName);
获取匹配到的所有元素中的第一个元素的指定属性的属性值. - 调用形式:$("xxx").attr(attrName,value):
- 设置/新增匹配到的所有元素的指定属性的属性值
- 如果value=null,指定属性将被删除
- 调用形式:$("xxx").attr(attrObject):
用"属性-值"的键值对构成的对象来设置匹配到的所有元素的一个或多个属性. - 调用形式:$("xxx").attr(attrName,attrFn(index,val)):
用一个函数attrFn的返回值作为value来设置某一个匹配元素的指定属性.(attrFn函数的参数有明确规定:index--该匹配元素在jQuery对象中的index值,也就是它的键值.attr--当前该元素的该属性的值(旧值))
用法详解:
(1)..attr()源代码定义:
jQuery.fn.extend( {
attr: function( name, value ) {
return access( this, jQuery.attr, name, value, arguments.length > 1 );
}
}
可见,.attr的核心是函数access(),而该函数不需要实例即可调用,属于直接定义在jQuery上的'静态函数'.
jQuery.access()源代码定义:
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
var i = 0,
length = elems.length,
bulk = key == null; //bulk用于判断key值是否为null(注:null==undefined的结果为true)
// 设置多个值(当key参数为对象时,注:jQuery.type实现原理是[[class]])
if ( jQuery.type( key ) === "object" ) {
chainable = true;
for ( i in key ) {
access( elems, fn, i, key[ i ], true, emptyGet, raw );
}
// 设置一个值(当key为非对象类型时)
} else if ( value !== undefined ) {
chainable = true;
if ( !jQuery.isFunction( value ) ) {
raw = true; //判断value值是否为函数类型.如果不是函数,设置raw值,为if(fn)以及if(bulk)埋下伏笔
}
if ( bulk ) { //批处理
// 批处理是执行在整个属性集上的
if ( raw ) {
fn.call( elems, value );
fn = null;
// 当value为函数时又有点不同
} else {
bulk = fn;
fn = function( elem, key, value ) {
return bulk.call( jQuery( elem ), value );
};
}
}
if ( fn ) { //对elems中的每一个元素应用fn方法,第三个参数由raw决定
for ( ; i < length; i++ ) {
fn(
elems[ i ],
key,
raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) )
);
}
}
}
return chainable ? //返回值设定
elems :
// Gets
bulk ?
fn.call( elems ) :
length ? fn( elems[ 0 ], key ) : emptyGet;
}
如上图,由于access函数用途并不局限于我们的.attr(),作为像笔者一样的jQuery初学者,源代码中有许多代码语句我们不能很好的理解(比如:if(bulk)部分).由于暂时接触到的jQuery内容较少较浅,我们如果一味深究,可能既搞不清楚原理,还浪费时间.所以,我们可以用一种简化的思想来分析问题: 只关注代码中跟我们当前问题有关的部分,忽略无关的,用不到的部分.
具体做法:我们将.attr()的四种用法的实际传参情况带入jQuery.access函数的定义中,删除我们进不去的if语句代码块,只保留会用到的代码语句.
调用形式:$("xxx").attr(name)
attr定义:
attr: function( name, value=undefined ) {
return jQuery.access( this, jQuery.attr, name, value=undefined, arguments.length > 1 );
}
access调用简化:
var access = function( this, jQuery.attr, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) {
var i = 0,
length = this.length, //jQuery对象的length属性(jQuery对象总是有length属性,它是类数组对象)
bulk = false;
return jQuery.attr( this[0], name );
};
同样,我们找到jQuery.attr()静态方法的源代码定义,用同样的简化方法分析,得到:
jQuery.attr()完整源码:
attr: function( elem, name, value ) { // elem:DOM对象 name:属性名/键名 value:属性值
var ret, hooks,
nType = elem.nodeType; // 节点类型
// 屏蔽属性节点,文本节点与注释节点
if ( nType === 3 || nType === 8 || nType === 2 ) {
return;
}
// 当属性不支持getAttribute方法时,回调jQuery.prop()方法--从操作attribute变成了操作property
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}
//下面的都是DOM元素elem支持getAttribute的情况
// 所有标签特性(attributes)都是小写(处理兼容:有的浏览器对同一属性的名称可能大小写不停)
// 如果某一个是已定义的,抓取必要的钩子
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { // 非元素节点或者是XML文本中的元素
name = name.toLowerCase();
hooks = jQuery.attrHooks[ name ] ||
( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
}
if ( value !== undefined ) {//如果value在传参时未被忽略
if ( value === null ) {
jQuery.removeAttr( elem, name );//传入第三个参数为null时,调用jQuery.removeAttr移除对应属性
return;
}
if ( hooks && "set" in hooks &&
( ret = hooks.set( elem, value, name ) ) !== undefined ) {
return ret;
}
elem.setAttribute( name, value + "" );
return value;
}
if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
return ret;
}
ret = jQuery.find.attr( elem, name );
// 不存在的属性会返回null,我们将之统一为undefined
return ret == null ? undefined : ret;
}
jQuery.attr()简化:
attr: function( elem, name, value=undefined ) { // elem:DOM对象 name:属性名/键名 value:属性值
var ret, hooks,
nType = 1;
ret = jQuery.find.attr( elem, name );
return ret;
}
其中,唯一不确定的是jQuery.find.attr,然而我们继续找下去则是有关Sizzle选择器引擎的问题,这对于我们初学者来说过于复杂.因此,我们再简化一下,带入实际情景,检测这一函数的输出:
var $p = $('#jQueryTest')[0];
console.log(jQuery.find.attr($p,'id')); //jQueryTest
因此,大概知道该函数该种传参情况下的作用是返回指定DOM元素的指定属性的值.
1.由jQuery.access简化代码中的return jQuery.attr( this[0], name );
可知,只传入一个name参数的情况下,确实只会返回jQuery对象中的索引为'0'的DOM对象的指定属性的属性值.
2.由jQuery.att()完整代码中
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}
可知:如果不支持get/setAttibute,那么原来的针对特性(attibute)的操作就会变成DOM元素属性(property)的操作.
调用形式:$("xxx").attr(name,value);
attr定义:
attr: function( name, value) { //此时的this是一个类数组
return jQuery.access( this, fn=jQuery.attr, name, value, chainable=true);
}
access调用简化:
var access = function( this, jQuery.attr, name, value, chainable=true, emptyGet=undefined, raw=undefined ) {
var i = 0,
length = this.length, //jQuery对象的length属性,表示找到的匹配的DOM元素的个数
bulk = false;
chainable = true;
if ( !jQuery.isFunction( value ) ) { //当value值不为函数时,设置raw为true,这是为了下一步if(jQuery.attr)中的raw判断做铺垫
raw = true;
}
if ( jQuery.attr ) { //jQuery.attr,为true
for ( ; i < length; i++ ) { //用for循环是因为此时的this是一个包含多个DOM元素的jQuery对象
jQuery.attr(
this[ i ],
name,
raw ? value : value.call( elems[ i ], i, jQuery.attr( this[ i ], name ) )
);//raw为true,也就是value不为函数时,用value作第三参数
}
}
}
return this; //返回jQuery对象本身
};
而,我们用简化的方法分析此种情况下的jQuery.attr(this,name,value):
attr: function( this[i], name, value ) {
var ret, hooks,
nType = this[i].nodeType;
if ( value !== undefined ) { //判断为true,进入if语句
if ( value === null ) {
jQuery.removeAttr( this[i], name );//如果value为null,删除该jQuery对象的所有匹配元素的指定属性
return;
}
this[i].setAttribute( name, value + "" );//设置当前DOM元素的指定属性的属性值
return value;
}
ret = jQuery.find.attr( this[i], name ); //删除了属性,返回null;否则,返回指定属性的属性值
return ret == null ? undefined : ret; //如果删除了指定属性,返回undefined;如果修改了属性,返回指定属性值
}
调用形式:$("xxx").attr(attrObject);
attr定义:
attr: function( name=attrObject ) {
return jQuery.access( this, jQuery.attr, name=attrObject, value=undefined, false);
}
access调用简化:
var access = function( this, fn, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) {
var i = 0,
length = this.length, //元素的length属性
bulk = false;
// 设置多个value值
if ( jQuery.type( name ) === "object" ) { //如果传入的name形参为对象类型
chainable = true;
for ( i in name ) { //对每一个对象中的属性名及属性值再次调用本身(递归)
access( this, fn, i, name[ i ], true, emptyGet, raw );
}
}
return elems; //返回jQuery对象本身
};
可见,对于一个由"属性-属性值"键值对构成的对象,会对其中的每一个属性都调用access设置一次.由于代码中使用的for-in循环,所以enumerable为false的键值对是无效的.
调用形式:$("xxx").attr(name,attrFn);
attr定义:
attr: function( name, value=attrFn ) {
return jQuery.access( this, jQuery.attr, name, value=attrFn, chainable=true );
}
access调用简化:
var access = function( this, jQuery.attr, name, value=attrFn, chainable=true, emptyGet=undefined, raw=undefined ) {
var i = 0,
length = this.length, //jQuery对象的length属性
bulk = false;
chainable = true;
if ( jQuery.attr ) { //true,进入if语句
for ( ; i < length; i++ ) {
jQuery.attr(
this[ i ],
name,
attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) ) // 调用attrFn,其返回值作为第三个参数
);
}
}
return elems; // 返回jQuery对象本身
};
由 [特别注意:attrFn的两个参数虽然有规定,但是不需要我们真的传参,而是函数体内部使用索引值或者当前属性值的一个接口]attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) )
可知,attrFn的参数限制就是源自这一行代码:(this[i]是调用attrFn的元素,后面两个是参数,一个是jQuery对象中的索引值,一个是当前元素的指定属性name的值的查询返回)
jQuery属性操作之.attr()的更多相关文章
- JQuery属性操作之attr()和prop()的区别
代码示例: <!doctype html> <html lang="en"> <head> <meta charset="UTF ...
- jquery——属性操作、特殊效果
1. attr().prop() 取出或者设置某个属性的值 <!DOCTYPE html> <html lang="en"> <head> &l ...
- jquery 属性操作 attr( ) prop()css( )区别
一 attr () 和 prop( ) 操作属性 谈谈我的总结: 1 2 1 属性的定义,根据W3C手册所述:属性包括,标准属性:id class style title 语言属性 lang dir以 ...
- jQuery 属性操作attr().prop().text().html().val()
这些方法用于获取和设置 DOM 元素的属性. 一.attr(): <!--样式:在style里面写的,用css来操作.--> <!--属性:在元素里面写的,用attr方法操作.--& ...
- jQuery属性操作
jQuery 的属性操作的核心部分其实就是对底层 getAttribute().setAttributes()等方法的一系列兼容性处理 ...if ( notxml ) { name = name.t ...
- jQuery源代码学习之八——jQuery属性操作模块
一.jQuery属性模块整体介绍 jQuery的属性操作模块分四个部分:html属性操作,dom属性操作,类样式操作,和值操作. html属性操作(setAttribute/getAttribute) ...
- jQuery 属性操作和CSS 操作
如有在jQuery方法中涉及到函数,此函数必定会返回一个数值(函数由于运行次数不同触发一些不同效果) jQuery 属性操作方法(以下方法前些日子学习过,不再赘述) addClass() attr() ...
- python全栈开发day48-jqurey自定义动画,jQuery属性操作,jQuery的文档操作,jQuery中的ajax
一.昨日内容回顾 1.jQuery初识 1).使用jQuery而非JS的六大理由 2).jQuery对象和js对象转换 3).jQuery的两大特点 4).jQuery的入口函数三大写法 5).jQu ...
- jQuery属性操作(四)
通过阅读jQuery为属性操作封装的基本方法和为处理兼容性问题提供的hooks,发现jQuery在属性操作方面并没有做过多的设计,只是处理一下兼容性问题,然后调用基础的DOM操作方法.以下是对JQue ...
随机推荐
- Sqlite EF6注册
在EF6使用Sqlite的时候.Sqlite需要安装sqlite-netFx40-setup-bundle-x64-2010-1.0.97.0.exe.我不想在项目发布的时候,安装的时候执行该程序,于 ...
- SqlServer数据库(可疑)的解决办法
当数据库发生这种操作故障时,可以按如下操作步骤可解决此方法, 打开数据库里的Sql 查询编辑器窗口,运行以下的命令. // 1.使用指定值强制重新配置:(1.0表示为真假) sp_configure ...
- python之路——进程
操作系统背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其 ...
- 3D旋转相册的实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 沉淀再出发:java的文件读写
沉淀再出发:java的文件读写 一.前言 对于java的文件读写是我们必须使用的一项基本技能,因此了解其中的原理,字节流和字符流的本质有着重要的意义. 二.java中的I/O操作 2.1.文件读写的本 ...
- loadrunner测试c/s架构的应用系统
用LoadRunner测试c/s架构的软件,怎样去选择协议,困扰了我很久,看到这篇文章,感觉有点收获,所以特意转了过来,希望对大家有用. 首先,什么是协议?协议无非就是一个约定,关于数据包发送的格式的 ...
- node.js和MongoDB学习网址
回想我写的node.js和MongoDB的博客,都是菜鸟教程那里的知识,所以我打算不写了,那些都是基础,在项目开发中,我发现单单有那些基础不行,这些基础可以尽快学好,然后学习项目开发过程 下面是两个教 ...
- Phonegap 目录结构介绍
1.Src 该目录包含了所有用户要创建的 Java 源文件 2.gen 为开发工具自动创建 3.assets 目录 用于方一些资源文件 css js html 4.res 目录该目录包含了所有的资源文 ...
- 【[HAOI2012]高速公路】
披着期望外衣的数据结构? 非常毒瘤 我们要求得期望其实就是 \[\frac{\sum_{i=l}^{r}\sum_{j=i+1}^{r}dis(i,j)}{\binom{r-l+1}{2}}\] 好像 ...
- MyBatis使用自定义TypeHandler转换类型的实现方法
From: http://www.manongjc.com/article/15577.html 这篇文章主要介绍了MyBatis使用自定义TypeHandler转换类型的实现方法,本文介绍使用Typ ...