jQuery的属性操作模块总共有4个部分,本篇说一下第1个部分:HTML特性部分,html特性部分是对原生方法getAttribute()和setAttribute()的封装,用于修改DOM元素的特性的

jQuery的静态方法含有如下API:

  • $.attr(elem, name, value)  ;设置或读取html属性,该方法有三种用法:

·$.attr(elem,name,null)       ;如果value为null则调用jQuery.removeAttr(elem, name)删除该属性
                    ·$.attr(elem,name,value)    ;设置elem元素的name属性值为value。
                    ·$.attr(elem,name)              ;获取elem元素的name属性

  • $.removeAttr(elem, name)  ;从DOM元素elem上移除name属性,name可以是单个字符串,也可以是空格分隔的多个html属性。对于应布尔属性会同步设置对应的DOM属性为false。

jQuery/$ 实例方法(可以通过jQuery实例调用的):

  • attr(name, value)           ;移除、设置html属性,有以下方法

      ·attr(obj)             ;参数1是对象时                             ;access()函数中验证 表示一次性设置多个属性
      ·attr(name,value)       ;为每个匹配元素设置一个HTML属性                  ;value可以是一个函数,取值为返回值,也可以为null时表示删除该属性    
      ·attr(name,NULL)         ;参数2为NULL时表示删除所有匹配元素的name特性,间接调用removeAttr()
      ·attr(name)              ;参数1是字符串时,参数2未指定或者设置为false    ;表示获取第一个匹配元素的HTML属性值。

  • removeAttr(name)                    ;移除每一个匹配元素的一个或多个HTML属性,name是要是移除的html属性,多个可以用空格分隔

举个栗子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<a>链接</a>
<button>淘宝</button> <!--点击后a标签将导航到淘宝-->
<button>百度</button> <!--点击后a标签将导航到百度-->
<button>移除</button> <!--点击后a标签将取消导航-->
<script>
let a = document.getElementsByTagName('a')[0], //获取a标签的引用
b1 = document.getElementsByTagName('button')[0], //淘宝按钮的引用
b2 = document.getElementsByTagName('button')[1], //百度按钮的引用
b3 = document.getElementsByTagName('button')[2]; //移除按钮的引用
b1.addEventListener('click',function(){
$.attr(a,'href','http://www.taobao.com'); //通过jQuery的静态方法设置href属性
})
b2.addEventListener('click',function(){
$('a').attr('href','http://www.baidu.com') //通过jQuery的实例方法设置href属性
})
b3.addEventListener('click',function(){
$("a").removeAttr('href') //移除href属性
})
</script>
</body>
</html>

渲染的页面如下:

此时对应的DOM结构如下:

当我们点击淘宝按钮后页面变为了如下:

DOM修改了这样子:

此时点击这个a标签将链接到淘宝网,然后我们点击百度,链接会链接到百度去的,最后点击移除时,该a标签又会变为初始化的状态。这就是jQuery的html特性操作

源码分析


$.attr和$.removeAttr实现如下:

jQuery.extend({
attr: function( elem, name, value, pass ) { //设置或读取html属性,是对原生方法getAttribute()和setAttribute()的简化
var ret, hooks, notxml,
nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { //如果elem为空 或者是文本、注释、属性节点
return; //直接返回,不接着处理
} if ( pass && name in jQuery.attrFn ) {
return jQuery( elem )[ name ]( value );
} // Fallback to prop when attributes are not supported
if ( typeof elem.getAttribute === "undefined" ) { //如果不支持方法getAttribute
return jQuery.prop( elem, name, value ); //则调用对应的DOM属性
} notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); //判断elem是否不是xml文档元素 // All attributes are lowercase
// Grab necessary hook if one is defined
if ( notxml ) {
name = name.toLowerCase();
hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
} if ( value !== undefined ) { //如果传入了参数value,表示是设置值 if ( value === null ) { //若值是null,则移除该name属性
jQuery.removeAttr( elem, name );
return; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { //优先调用对应的修正对象的修正方法set()
return ret; } else {
elem.setAttribute( name, "" + value ); //否则调用原生方法setAttribute()设置html属性
return value;
} } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { //如果未传入参数value,优先调用对应的修正对象的修正方法get()
return ret; } else { ret = elem.getAttribute( name ); //否则调用原生方法getAttrubute()读取html属性。 // Non-existent attributes return null, we normalize to undefined
return ret === null ?
undefined :
ret;
}
}, removeAttr: function( elem, value ) { //从DOM元素上移除一个或多个html属性,多个html属性用空格分隔。是对removeAttribute的封装和扩展。
var propName, attrNames, name, l,
i = 0; if ( value && elem.nodeType === 1 ) { //如果设置了value参数 且 elem是一个元素节点
attrNames = value.toLowerCase().split( rspace ); //执行后attrNames是一个数组,保存了要移除的属性名:比如:Array [ "id", "name" ] rspace = /\s+/,
l = attrNames.length; //需要移除的属性的个数 for ( ; i < l; i++ ) { //遍历数组attrNames,逐个移除html属性。
name = attrNames[ i ]; //name是要移除的属性名 if ( name ) {
propName = jQuery.propFix[ name ] || name; //如果属性名name需要修正,则修正属性 // See #9699 for explanation of this approach (setting first, then removal)
jQuery.attr( elem, name, "" ); //先将html属性设置为空字符串,以解决Webkit内核浏览器不能
elem.removeAttribute( getSetAttribute ? name : propName ); //调用原生方法removeAttribute删除对应的属性,如果jQuery.support.getSetAttribute为true则删除name属性,如果为false,表示在IE6、7下则删除特殊属性。 // Set corresponding property to false for boolean attributes
if ( rboolean.test( name ) && propName in elem ) { //对应布尔属性,同步设置对应的DOM属性为false
elem[ propName ] = false;
}
}
}
}
},
/**/
})

对于jQuery实例来说,它调用了不同的工具函数,最后还是执行上面讲解的静态方法的,如下:

jQuery.fn.extend({
attr: function( name, value ) { //移除、设置html属性
return jQuery.access( this, name, value, true, jQuery.attr ); //调用了jQuery.access工具函数,参数5传入了jQuery.attr
}, removeAttr: function( name ) { //移除html属性
return this.each(function() { //通过each函数方法,依次执行jQuery.removeAttr()
jQuery.removeAttr( this, name );
});
},
/*略*/
})

由于jQuery中的特性、DOM属性和样式操作的函数参数可以是差不多的,jQuery就定义了一个access函数,为.attr()、.prop()、.css()提供支持,这样我们通过jQuery实例设置特性、属性和样式时可以传入的参数类型,例如:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<a>链接</a>
<script>
$('a').attr('href','http://www.cnblogs.com') //参数2是个字符串
$('a').attr('href',()=>'http://www.cnblogs.com') //参数2还是是个函数
$('a').attr({href:'http://www.cnblogs.com'}) //也可以传入一个对象
</script>
</body>
</html>

我们传入不同的参数,都可以实现设置特性的效果,这就是$.access的作用,$.access的源码实现如下:

jQuery.extend({
access: function( elems, key, value, exec, fn, pass ) { //为集合中的元素设置一个或多个属性值,或者读取第一个元素的属性值
var length = elems.length; // Setting many attributes
if ( typeof key === "object" ) { //如果key是对象,表示要设置多个属性,则遍历该对象循环执行.access函数
for ( var k in key ) {
jQuery.access( elems, k, key[k], exec, fn, value );
}
return elems;
} // Setting one attributes
if ( value !== undefined ) { //如果参数value不是undefined,表示要设置单个属性
// Optionally, function values get executed if exec is true
exec = !pass && exec && jQuery.isFunction(value); //修正exec参数。如果没有传入pass参数或者该参数值是false,且参数exec为true,且value是函数则设置exec为true,否则exec为false。 for ( var i = 0; i < length; i++ ) {
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); //遍历元素集合elems,为每个元素调用回调函数fn
} return elems; //遍历完成后返回元素elems。以支持链式操作
} // Getting an attribute
return length ? fn( elems[0], key ) : undefined; //当value参数为空,且元素集合elems不为空则获取第一个匹配元素相关的信息,即执行fn函数
},
/**/
})

writer by:大沙漠 QQ:22969969

之后的DOM属性和样式操作都会借用access这个工具方法的。

jQuery 源码分析(十二) 数据操作模块 html特性 详解的更多相关文章

  1. jQuery 源码分析(十四) 数据操作模块 类样式操作 详解

    jQuery的属性操作模块总共有4个部分,本篇说一下第3个部分:类样式操作部分,用于修改DOM元素的class特性的,对于类样式操作来说,jQuery并没有定义静态方法,而只定义了实例方法,如下: a ...

  2. jQuery 源码分析(十五) 数据操作模块 val详解

    jQuery的属性操作模块总共有4个部分,本篇说一下最后一个部分:val值的操作,也是属性操作里最简单的吧,只有一个API,如下: val(vlaue)        ;获取匹配元素集合中第一个元素的 ...

  3. jQuery 源码解析(二十二) DOM操作模块 复制元素 详解

    本节说一下DOM操作模块里的复制元素子模块,该模块可以复制一个DOM节点,并且可选择的设置是否复制其数据缓存对象(包含事件信息)和是否深度复制(子孙节点等),API如下: $.clone(elem, ...

  4. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  5. Vue.js 源码分析(十四) 基础篇 组件 自定义事件详解

    我们在开发组件时有时需要和父组件沟通,此时可以用自定义事件来实现 组件的事件分为自定义事件和原生事件,前者用于子组件给父组件发送消息的,后者用于在组件的根元素上直接监听一个原生事件,区别就是绑定原生事 ...

  6. 一个普通的 Zepto 源码分析(二) - ajax 模块

    一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...

  7. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

  8. jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解

    本节说一下DOM操作模块里的包裹元素子模块,该模块可将当前匹配的元素替换指定的DOM元素,有如下方法: wrap(html)               ;在每个匹配元素的外层添加一层DOM元素   ...

  9. jQuery 源码分析(十三) 数据操作模块 DOM属性 详解

    jQuery的属性操作模块总共有4个部分,本篇说一下第2个部分:DOM属性部分,用于修改DOM元素的属性的(属性和特性是不一样的,一般将property翻译为属性,attribute翻译为特性) DO ...

随机推荐

  1. 《软件安装》VMware 安装 centos8

    上期问题回顾 搞技术的同学应该都听过docker,那么请问docker和虚拟机有什么区别呢? 传统的虚拟机架构是:物理机 -> 宿主机操作系统 -> Hypervisor支持 -> ...

  2. 项目如何部署在linux系统上

    前面已经安装好centos的系统,网络配置,以及部署的环境已成功啦... 下面记录的是如何部署一个项目 四个步骤: (1)放war包 (2)执行数据库脚本 (3)修改数据库的配置文件 (4)重启tom ...

  3. dotnet core 调用electron来开发UI的探索

    先上仓库地址 https://github.com/lightszero/webwindow.netcore dotnet core 很喜欢,问题dotnet core 不包含GUI,经过一些尝试,觉 ...

  4. 获取windows操作系统所有用户

    一.知识点简单介绍 1. 利用WindowsApi获取 [DllImport("Netapi32.dll ")] extern static int NetUserEnum([Ma ...

  5. ASP.NET Core 3.0 gRPC 配置使用HTTP

    前言 gRPC是基于http/2,是同时支持https和http协议的,我们在gRPC实际使用中,在内网通讯场景下,更多的是走http协议,达到更高的效率,下面介绍如何在 .NET Core 3.0 ...

  6. 对象流,它们是一对高级流,负责即将java对象与字节之间在读写的过程中进行转换。 * java.io.ObjectOutputStream * java.io.ObjectInputStream

    package seday06; import java.io.Serializable;import java.util.Arrays; /** * @author xingsir * 使用当前类来 ...

  7. Customize the Application UI and Behavior 自定义应用程序UI和行为

    In XAF, the business model defines the database structure and UI appearance. Changes to your persist ...

  8. latex初步入门:springer llncs

    最近写一篇论文呢,使用到了latex,记录一下吧. 使用的是标准 : springer 的llncs类 核心:使用官方的samplepaper.tex基础上进行修改 这个是最快上手,也是最快能码出一篇 ...

  9. 应用DEV第三方界面控件制作批量添加水印程序

    本次应用DevExpress和C#语言制作了一个批量添加水印的程序,看界面效果图: 界面中既可以进行文字水印添加,也可以图片水印添加,同时还可以对水印的位置进行设置,比较实用! 文字水印的具体添加情况 ...

  10. 解决MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.问题

    突然发现昨天刚搭建的websocket不能连接了,提示: MISCONF Redis is configured to save RDB snapshots, but it is currently ...