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

  • addClass(value)      ;为匹配元素集合中的每个元素添加一个或多个类样式,通过修改DOM属性className来修改类样式,value可以是个以空格分隔的类样式或者一个函数(返回一个或多个以空格分隔的类样式)
  • hasClass(selector)       ;检测匹配元素中的任意元素是否含有指定的类样式,只要其中一个元素含有就返回true,selector是一个类样式。
  • removeClass(value)    ;从匹配元素集合中的每个元素上移除一个或多个或全部类样式,value可以为空(全部移除)、以空格分隔的类样式(移除多个样式),或者是个函数(该函数返回一个或多个以空格分隔的类样式)
  • toggleClass(value,stateVal) ;对设置或移除被选元素的一个或多个类进行切换,有五种用法

writer by:大沙漠 QQ:22969969

    ·toggleClass()                  ;未传入参数                    ;这时如果当前元素含有样式则移除所有类,如果没有则尝试恢复。
    ·toggleClass(stateVal)          ;只传入一个布尔值类型              ;如果stateVal是true,则等同于toggleClass();如果是false则总是移除所有类。
    ·toggleClass(value)           ;参数1是字符串或函数,未传入参数2        ;value是字符串时表示一个或多个样式,用空格分隔,下同;value是函数时返回字符串格式。如果匹配元素含有指定的类样式,则移除,否则添加该样式。
    ·toggleClass(value,stateVal)     ;参数1是字符串或函数,参数2是布尔值    ;当stateVal是true时总是添加,是false时则总是移除

对于toggleClass切换样式时,jQuery内部实现会将所有类暂时保存在数据缓存对象的__className__数据中,等下次恢复时尝试读取。

举个栗子吧:

<!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>
<style>
.color{color: #f00;}
.back{background: #ccc;}
</style>
</head>
<body>
<p>Hello World!</p>
<button id="b1">设置所有样式</button>
<button id="b2">切换color样式</button>
<button id="b3">取消所有样式</button>
<script>
let b1 = document.getElementById('b1'),
b2 = document.getElementById('b2'),
b3 = document.getElementById('b3');
b1.onclick = ()=>{
$('p').addClass('color back'); //添加所有样式
}
b2.onclick = ()=>{
$('p').toggleClass('color'); //切换color样式
}
b3.onclick = ()=>{
$('p').removeClass(); //取消所有样式
}
</script>
</body>
</html>

这里我们在style自定义了两个class:color和back,前者修改字体的颜色,后者修改字体的背景色,然后定义了三个按钮分别用于操作样式,渲染如下:

点击设置所有样式,将在p这个DOM元素上添加color和back两个class,如下:

当点击切换color样式时,由于p元素上的color这个class已经存在了,因此会取消掉:

当再次点击切换color样式这个按钮时,由于p元素上的color这个class已经取消了,因此此时会显示出来,如下:

当我们点击取消所有样式时将会把p元素上的所有class给删掉,又回到初始状态,如下:

源码分析


jQuery内部对于样式的操作是修改对应DOM元素的className属性来实现的,中间通过字符串的indexOf和replace操作实现查找和替换,对于添加样式和删除样式的逻辑如下:

jQuery.fn.extend({
addClass: function( value ) { //添加类样式
var classNames, i, l, elem,
setClass, c, cl; if ( jQuery.isFunction( value ) ) { //如果value是函数
return this.each(function( j ) {
jQuery( this ).addClass( value.call(this, j, this.className) ); //在每个匹配元素上执行该函数并且取其返回值作为待添加的类样式,然后调用.addClass(className)添加类样式。执行函数时,传入两个参数,分别是元素在集合中的下标位置和当前样式值。
});
} if ( value && typeof value === "string" ) { //如果value是字符串,可以是空格分隔的多个样式
classNames = value.split( rspace ); //用/\s+/对value进行分隔 for ( i = 0, l = this.length; i < l; i++ ) { //遍历匹配元素
elem = this[ i ]; if ( elem.nodeType === 1 ) { //只针对元素节点
if ( !elem.className && classNames.length === 1 ) { //如果elem.className不存在,且待添加的样式个数为1,则直接设置elem.className
elem.className = value; } else {
setClass = " " + elem.className + " "; //在待添加的类样式className前后加空格 for ( c = 0, cl = classNames.length; c < cl; c++ ) { //历要添加的类样式value
if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { //如果classNames中的某个样式不存在setClass中
setClass += classNames[ c ] + " "; //则添加该样式
}
}
elem.className = jQuery.trim( setClass ); //最后去除类样式两边的空格,再设置到elem.className中
}
}
}
} return this;
},
removeClass: function( value ) { //从匹配元素集合中的每个元素上移除一个或多个或全部类样式。通过修改DOM属性className来移除类样式。
var classNames, i, l, elem, className, c, cl; if ( jQuery.isFunction( value ) ) { //如果value是一个函数
return this.each(function( j ) { //遍历匹配元素
jQuery( this ).removeClass( value.call(this, j, this.className) ); //调用每个匹配元素的removeClass()函数,参数是value函数的返回值
});
} if ( (value && typeof value === "string") || value === undefined ) { //如果value存在且是一个字符串 或者 value未定义
classNames = ( value || "" ).split( rspace ); //用空白符分隔value以支持一次移除多个类样式。这里如果value是空的,那么结果是[""],该数组的length等于1 for ( i = 0, l = this.length; i < l; i++ ) { //遍历匹配元素
elem = this[ i ]; //elem是匹配的元素 if ( elem.nodeType === 1 && elem.className ) { //只支持已经设置了className的元素节点。
if ( value ) { //如果传入了value值,则表示是设置样式
className = (" " + elem.className + " ").replace( rclass, " " ); //classNames是当前元素的类样式,两边加个空格,再去除出换行、制表、回车符。var rclass = /[\n\t\r]/g,
for ( c = 0, cl = classNames.length; c < cl; c++ ) { //遍历要移除的类样式数组classNames
className = className.replace(" " + classNames[ c ] + " ", " "); //调用字符串方法replace()逐个从当前类样式中移除
}
elem.className = jQuery.trim( className ); //去掉空白字符,在设置elem.className属性 } else {
elem.className = "";
}
}
}
} return this;
},
/*略*/
})

当我们在页面里做各种动画效果时还是会用到这个API的,挺方便的,配合css可以实现各种的动画效果。

jQuery 源码分析(十四) 数据操作模块 类样式操作 详解的更多相关文章

  1. jQuery 源码分析(十二) 数据操作模块 html特性 详解

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

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

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

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

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

  4. Vue.js 源码分析(十九) 指令篇 v-html和v-text指令详解

    双大括号会将数据解释为普通文本,而非 HTML 代码.为了输出真正的 HTML,你需要使用 v-html 指令,例如: <!DOCTYPE html> <html lang=&quo ...

  5. jQuery 源码分析(五) map函数 $.map和$.fn.map函数 详解

    $.map() 函数用于使用指定函数处理数组中的每个元素(或对象的每个属性),并将处理结果封装为新的数组返回,该函数有三个参数,如下: elems Array/Object类型 指定的需要处理的数组或 ...

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

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

  7. jQuery 源码分析(十六) 事件系统模块 底层方法 详解

    jQuery事件系统并没有将事件监听函数直接绑定到DOM元素上,而是基于数据缓存模块来管理监听函数的,事件模块代码有点多,我把它分为了三个部分:分底层方法.实例方法和便捷方法.ready事件来讲,好理 ...

  8. jQuery 源码分析(十八) ready事件详解

    ready事件是当DOM文档树加载完成后执行一个函数(不包含图片,css等),因此它的触发要早于load事件.用法: $(document).ready(fun) ;fun是一个函数,这样当DOM树加 ...

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

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

随机推荐

  1. Markdown语法教程

    标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 效果如下: 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 段落 换 ...

  2. go语言之面向对象

    Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...

  3. 【Java基础】正则表达式

    目录 正则表达式 什么正则表达式 普通字符 预定义字符 特殊字符 数量限定字符 定位字符 选择符和分组 反向引用 预搜索 运算符的优先级 常用正则 附录 正则表达式 本文的大部分内容转载自正则表达式从 ...

  4. 1025 PAT Ranking 双重排序

    Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhe ...

  5. React躬行记(1)——函数式编程

    函数式编程是React的精髓,在正式讲解React之前,有必要先了解一下函数式编程,有助于更好的理解React的特点.函数式编程(Functional Programming)不是一种新的框架或工具, ...

  6. jsp日期显示格式化-<fmt:formatDate

    在处理从数据库读取到的日期的时候发现,视图层通过EL表达式获取的日期格式跟预期不符 为格林威治时间(GMT)格式 解决: 1.引入JSTL标签 <%@ taglib prefix="f ...

  7. 资深程序员对于Python各个方向的面试经验分享,非常给力!

    之前早有前辈们说过,"裸辞一时爽,一直裸辞一直爽",这话一点不假,裸辞你要面临没有收入来源,但是每天眼睁睁看着各种花销不断支出的煎熬,我主要是觉得一边在上家公司工作一边去下家面试可 ...

  8. 在vue项目中的js文件里使用vue实例

    参考的网址:https://blog.csdn.net/weixin_34353714/article/details/86958742 不为其他,就为了记录一下,方便以后查看: 第一种方法: 1.首 ...

  9. 随意看看AtomicInteger类和CAS

    最近在读jdk源码,怎么说呢?感觉收获还行,比看框架源码舒服多了,一些以前就感觉很模糊的概念和一些类的用法也清楚了好多,举个很简单的例子,我在读Integer类的时候,发现了原来这个类自带缓存,看看如 ...

  10. Android App图片资源文件压缩利器McImage

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/195 Android App图片资源文件压缩利器McIma ...