elem.toggleClass(value,stateVal)
- 2个实参,第一个是字符串,第二个是 布尔值
- 第二个参数为true ,添加class value,
- 第二个参数为false,删除class value
- 第一个参数是函数
- 遍历elem中 的每个dom元素执行回调函数,回调函数的this值指向dom元素,第一个参数是dom元素的下标,第二个参数为元素当前的class,第三个参数为toggleClass的第二个参数,然后吧回调函数的返回值作为toggleClass的第一个参数重新执行toggleClass方法
- 只有一个参数
- 类型为string ,如果已经存在这个class,则删除,如不过不存在,则添加
- 值为 false 清空class
- 没有参数
- 如果有class,把class缓存起来并清除class
- 如果没有cass,吧缓存的class添加回去
jQuery.fn.extend({
toggleClass: function( value, stateVal ) {
var type = typeof value;
// 获取第一个参数的数据类型
if ( typeof stateVal === "boolean" && type === "string" ) {
// 第一个参数是个字符串并且第二个参数是布尔值
return stateVal ? this.addClass( value ) : this.removeClass( value );
//当第二个参数为true时,把value作为className添加进元素
//当第二个参数为false时,移除元素中的 value class
}
//只有一个参数并且是函数
if ( jQuery.isFunction( value ) ) {
//第一个参数是函数
//对当前每个jq对象执行一次函数
//this指向jq对象数组里的每个元素,i是其下标
return this.each( function( i ) {
jQuery( this ).toggleClass(
value.call( this, i, getClass( this ), stateVal ),
//把i 当前元素的className,stateVal作为参数传递value函数
//并把value的this指向当前元素
//把返回的值作为第一个参数重新调用函数
stateVal
);
} );
}
//没有参数或只有一个参数是string或boolean
return this.each( function() {
var className, i, self, classNames;
if ( type === "string" ) {
//第一个参数为字符串类型
// Toggle individual class names
i = 0;
self = jQuery( this );
classNames = value.match( rnothtmlwhite ) || [];
///rnothtmlwhite = ([^\x20\t\r\n\f]+/g)
//把value根据分隔符拆分成数组,没有匹配到就返回空数组
while ( ( className = classNames[ i++ ] ) ) {
// Check each className given, space separated list
if ( self.hasClass( className ) ) {
//如果元素有className,则删除
self.removeClass( className );
} else {
//如果没有,则添加
self.addClass( className );
}
}
// Toggle whole class name
} else if ( value === undefined || type === "boolean" ) {
//value为undefined或则boolean
className = getClass( this );
if ( className ) {
//如果元素本来有classname,那么先缓存起来
// Store className if set
dataPriv.set( this, "__className__", className );
}
// If the element has a class name or if we're passed `false`,
// then remove the whole classname (if there was one, the above saved it).
// Otherwise bring back whatever was previously saved (if anything),
// falling back to the empty string if nothing was stored.
if ( this.setAttribute ) {
//元素存在setAttribute方法
this.setAttribute( "class",
className || value === false ?
"" :
dataPriv.get( this, "__className__" ) || ""
//className有值 或value === false 删除所有classname
//
);
}
}
} );
},
each: function( callback ) {
return jQuery.each( this, callback );
},
})
jQuery.extend({
//遍历对象的每个元素,执行回调函数,回调函数的this指向对象成员
each: function( obj, callback ) {
var length, i = 0;
//判断obj是否是类数组对象,比如元素的jq对象
if ( isArrayLike( obj ) ) {
length = obj.length;
for ( ; i < length; i++ ) {
//遍历obj对象,执行回调函数
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
break;
}
}
} else {
for ( i in obj ) {
//遍历obj对象,执行回调函数
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
break;
}
}
}
return obj;
}
})
//判断是否为类数组对象
function isArrayLike( obj ) {
var length = !!obj && "length" in obj && obj.length,
//length=obj.length,如果不存在,就=false
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
//如果obj是function或window对象,返回false
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
//如果obj是个数组类型,返回true
//length存在并且等于0,返回true
//length存在并且是数值类型而且大于0,obj存在length - 1元素,返回true
//如果上面所有条件都不满足,返回false,不是个类数组对象
}