jQuery提供了4个操作class的方法:
jQuery.fn.extend({
// ...
// 为匹配的每个元素增加指定的class(es)
addClass: function( value ) {},
// 从匹配的每个元素上,移除 一个 或 多个 或 全部class
removeClass: function( value ) {},
// 对匹配元素集中的每个元素增加或删除一个或多个class
toggleClass: function( value, stateVal ) {},
// 检测匹配的元素是否指定了传入的class,只要有一个匹配就返回true
hasClass: function( selector ) {},
// ...
});
.addClass():
为匹配的每个元素增加指定的class(es)
.addClass(className):className添加到每一个匹配元素的class属性上的一个或多个class
.addClass(function(index,currentClass)):function(index,currentClass)返回一个或多个class名称,多个class用空格分开这些class被添加到现有的class属性中
index 单签元素在集合中的位置 currentClass 当前的class名 this 指向集合中的当前元素
.addclass()
addClass:function(value){
var classNames,i,l,elem,setClass,c,cl;
//value为函数
if(jQuery.isFunction(value)){
return this.each(function(j){
//this.className 获取当前的class的值
jQuery(this).addClass(value.call(this,j,this.className));
});
}
//vlaue为数组
if(value && typeof vlaue === "string"){
classNames = value.split(rspace);//用空白符风格classNames 转换为数组
for(i=0,l=this.length;i<l;i++){//遍历所有匹配的元素 缓存长度
elem = this[i];//缓存下来 避免再次查找
if(elem.nodeType === 1){
//如果没有class属性 或class属性为空字符串 classNames.length ===1 ,多于一个去重
if(!elem.className && classNames.length === 1){
elem.className = value;
}else{//已有className 或 classNames长度大于1
setClass = " " + elem.className + " ";
for(c = 0;cl = classNames.length;c<cl:c++){
//不理解
if(!~setClass.indexOf(" " + classNames[c] + " ")){
setClass += classnames[c] + " ";//追加,最后加一个空格
}
}
//去除首尾空白符
elem.className = jQuery.trim(setClass);
}
}
}
}
},
.removeClass():
从匹配的每个元素上,移除 一个 或 多个 或 全部class
如果是函数,执行函数,将返回结果再次调用jQuery.fn.removeClass
如果是字符串,在elem.className和classNames[c]前后加空格,判断replace删除
如果是undefined,置为空字符串elem.className = ""
className 一个或多个以空格分隔的class,这些class将被从匹配元素的class属性中移除
.removeClass( function(index, class) )
function(index, class) 函数返回一个或多个以空格分隔的class,用于移除。
.removeClass()
removeClass:function(value){
var classNames,i,l,elem,className,c,cl;
//如果传入函数则执行函数 取返回值作为要移除的classNames
if(jQuery.isFunction(value)){
return this.each(function(j){
//this.calssName 获取当前的class值
jQuery(this).removeClass(value.call(this,j,this.className));
});
}
if((value && typeof value === "string") || value === undefined){
// value || "" 避免空引用错误的常用技巧
classNames = (value || "").split(rspace);//分割数组
for(i=0,l=this.length;i<l;i++){//遍历所有匹配的元素 缓存长度
elem = this[i];//缓存下来 避免再次查找
if(elem.nodeType === 1 && elem.className){
//如果有value,则从当前className属性中删除
if(value){
className = (" " + elem.className + " ").replace(rclass," ");//前后加空格 将\n \t \r替换为空格
for(c = 0;cl = classNames.length;c<cl:c++){
className = className.replace(" " + classNames[c] + " "," ");//将要删除的className替换为空格
}
// 删除前后的空白符,然后赋值给elem.className
elem.classname = jQuery.trim(className);
}else{
elem.className = "";
}
}
}
return this;
},
.toggleClass():
对匹配元素集中的每个元素增加或删除一个或多个class
增加或删除的行为依赖当前元素是否含有指定的class,或switch参数的值
.toggleClass( className ) 1.0
className 一个或多个class(用空格隔开),在匹配元素集的每个元素上切换class
如果集合中的某个元素含有指定的className,className会被删除;如果没有会添加。
.toggleClass( className, switch ) 1.3
switch 一个布尔值,依据这个布尔值来决定是添加(true)还是删除(false)
.toggleClass( [switch] ) 1.4
switch 一个布尔值,依据这个布尔值来决定是添加还是删除
.toggleClass( function(index, class, switch) [, switch] ) 1.4
function(index, class, switch) 函数返回用于切换的calss名称
index是当前元素是集合中的下标位置, class是当前元素的就class值
核心技巧:调用addClass 或 removeClass 或 直接赋值elem.className
.toggleClass()
toggleClass: function( value, stateVal ) {
var type = typeof value, // value的类型,可以是字符串(一个或多个class),也可以是function,(undefined和boolean是另说)
isBool = typeof stateVal === "boolean";
// 如果是函数,则执行函数,用函数的返回值作为切换的className,迭代调用jQuery.fn.toggleClass
if ( jQuery.isFunction( value ) ) {
return this.each(function( i ) {
// 迭代调用
jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
});
}
// 遍历当前jQuery对象
return this.each(function() {
// value是字符串,挨个遍历value中的类样式,switch的优先级高于hasClass,hasClass返回false则addClass返回true则removeClass
if ( type === "string" ) {
// toggle individual class names
// 切换单个class
var className,
i = 0,
self = jQuery( this ),
state = stateVal,
classNames = value.split( rspace ); // 可能有多个class,用空白符分割
// 因为不需要在className前后加空格,所以这里可以将取值、自增、判断合并为while循环。很好的技巧。
while ( (className = classNames[ i++ ]) ) {
// check each className given, space seperated list
/*
* 如果state是布尔值,则以state为准,否则检查是否含有className
* 含有 state为false,表示需要addClass;反之需要removeClass
* 这个三元表达式合并了state与self.hasClass的判断,小技巧
*/
state = isBool ? state : !self.hasClass( className );
//删除还是添加
self[ state ? "addClass" : "removeClass" ]( className );
}
/*
* type === "undefined" 未指定参数,即.toggleClass()
* type === "boolean" 省略className,只有switch,即.toggleClass( switch )
*/
// 未指定参数 或 只有switch,则切换整个className
} else if ( type === "undefined" || type === "boolean" ) {
// 如果有className,则缓存下来,以便再次调用时恢复
if ( this.className ) {
// 以内部数据的方式缓存
jQuery._data( this, "__className__", this.className );
}
/*
* 切换整个className
* 又是一个合并了几个判断条件的三元,分解为四个逻辑:
* this.className && value 是 true/undefined ""
* this.className && value 是 false ""
* !this.className && value 是 true/undefined jQuery._data( this, "__className__" ) || ""
* !this.className && value 是 false ""
*
* 分析一下上边的四个逻辑,可以总结如下:(value用switch代替)
* 1. 如果this.className存在,无论switch什么状态(true/false/undefined),都置为空""
* 2. 如果this.className不存在,如果switch为true/undefined,才会恢复className
* 3. 如果this.className不存在,如果switch为false,置空(保持不变)
*
* .toggleClass( switch )的用法可以总结如下:
* 1. switch为true,进行正常的切换,等价于.toggleClass()
* 2. switch为false,总是置空
*/
this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
}
});
},
.hasClass():
检测匹配的元素是否指定了传入的class,只要有一个匹配就返回true
.hasClass() 检测匹配的元素是否指定了传入的class,只要有一个匹配就返回true;元素可能有多个class,在HTML中多个class用空格隔开;
如果遇到某个元素含有指定的className,.hasClass()将会返回true,即便还指定了其他的className。
.hasClass()
hasClass:function(selector){
var className = " " + selector + " ",//前后加空格
i =0,
l = this.length;
for(;i<l:i++){
// 必须是Element,技巧同样是前后加空格,同样是indexOf
if(this[i].nodeType === 1 && ( " " + this[i].className + " ").replcae(rclass," ").indexOf(className) > -1){
return true;
}
}
return false;
}