欢迎来我的专栏检察系列文章。
眼看 jQuery 的源码就快到头了,背面另有几个重要的内容,包含 ajax 和动画操纵,加油把它们看完,百度前端学院的新一批课程也最先了。百度前端学院。
class 的的操纵应当算是比较兴奋的,由于内容不是许多,或者说,内容涉及到的原生操纵不是很大,就一个 className 或 getAttribute,重要照样来看下它涉及到的一些兼容性操纵。
class 操纵
先来讲一个比较风趣的 class 操纵,先把链接贴上。
js 有一个非常大的缺点,就是无法控制伪元素的款式,比方 after 和 before,这模样会落空许多兴趣(一样也带来了许多兴趣)。上面的链接是 stackoverflow 的解答。
1. class 体式格局
经由过程事前定义 class 的体式格局来处置惩罚:
p:before {
content: "c1"
}
p.click:before {
content: "click"
}
// js
$("p").on("click", function(){
$(this).toggleClass('click');
})
2. 内联 style 体式格局
这类体式格局不文雅,也是一种处置惩罚方法。
var str = "click";
$('<style>p:before{content:"' + str + '""}</style>').appendTo('head');
3. jQuery data-attr 来处置惩罚
这类体式格局是依托 content 的特征:
p:before {
content: attr(data-click);
}
//js
var str = 'click';
$("p").on("click", function(){
$(this).attr("data-click", str);
})
这类体式格局应当是动态转变。
jQuery 的运用照样挺普遍的。
fn.hasClass
jQuery 中的 class 操纵照样很有意义,会用到许多正则表达式,我超喜好正则表达式的。
假如让我用原生的 js 来完成 class 操纵,我会想到两种体式格局,一种是 className,它的兼容性非常好,一切浏览器都支撑,包含 mobile。第二个是 getAttribute,也是一切浏览器都支撑(有版本限定)。
先从 hasClass 提及吧:
// 猎取 class-name
function getClass( elem ) {
return elem.getAttribute && elem.getAttribute( "class" ) || "";
}
// 将 class name 举行处置惩罚
function stripAndCollapse( value ) {
var tokens = value.match( /[^\x20\t\r\n\f]+/g ) || [];
return tokens.join( " " );
}
jQuery.fn.extend( {
hasClass: function( selector ) {
var className, elem,
i = 0;
className = " " + selector + " ";
while ( ( elem = this[ i++ ] ) ) {
if ( elem.nodeType === 1 &&
( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
return true;
}
}
return false;
}
} );
能够看出 getClass
函数运用的是 getAttribute
要领。
fn.addClass
接下来看一下增加 add:
jQuery.fn.extend( {
addClass: function( value ) {
var classes, elem, cur, curValue, clazz, j, finalValue,
i = 0;
// 参数为函数...
if ( jQuery.isFunction( value ) ) {
return this.each( function( j ) {
jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
} );
}
if ( typeof value === "string" && value ) {
// 能够增加多个 class
classes = value.match( /[^\x20\t\r\n\f]+/g ) || [];
while ( ( elem = this[ i++ ] ) ) {
curValue = getClass( elem );
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
if ( cur ) {
j = 0;
while ( ( clazz = classes[ j++ ] ) ) {
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
cur += clazz + " ";
}
}
// 在这里 set class,有个 diff 推断
finalValue = stripAndCollapse( cur ); // 去除两侧空格
if ( curValue !== finalValue ) {
elem.setAttribute( "class", finalValue );
}
}
}
}
return this;
}
} );
jQuery 大抵处置惩罚的思绪是如许的:先把当前 elem 中的 class 取出来 cur
,要增加的 value
假如在 cur 中 indexOf
的值显现不存在,就在 cur 背面加上 value。
fn.removeClass
删除可能要贫苦一点点:
jQuery.fn.extend( {
removeClass: function( value ) {
var classes, elem, cur, curValue, clazz, j, finalValue,
i = 0;
// 不知道在那里用到 value 为 function 状况
if ( jQuery.isFunction( value ) ) {
return this.each( function( j ) {
jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
} );
}
// 无参数示意 移除一切的 class ...
if ( !arguments.length ) {
return this.attr( "class", "" );
}
if ( typeof value === "string" && value ) {
classes = value.match( rnothtmlwhite ) || [];
while ( ( elem = this[ i++ ] ) ) {
curValue = getClass( elem );
// This expression is here for better compressibility (see addClass)
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
if ( cur ) {
j = 0;
while ( ( clazz = classes[ j++ ] ) ) {
// 移除一切须要移除的 class
while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
cur = cur.replace( " " + clazz + " ", " " );
}
}
// Only assign if different to avoid unneeded rendering.
finalValue = stripAndCollapse( cur );
if ( curValue !== finalValue ) {
elem.setAttribute( "class", finalValue );
}
}
}
}
return this;
}
} );
能够看出 remove 的操纵基本上和 add 一样,只不过处置惩罚 class 的时刻略有不同:
// 这里用 while,是有技能的
while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
cur = cur.replace( " " + clazz + " ", " " );
}
用 replace 替代婚配的 clazz 为空格。
fn.toggleClass
toggleClass 运用的频次也比较高。
先来看看大抵用法,你肯定会疏忽它的第二个参数的意义。.toggleClass(),当第二个参数为 true 的状况,就是 addClass,为 false 时,removeClass,从源码来看,就是直接挪用的这两个函数。
除了两个参数,另有没有参和只要 false 状况,下面也都有明白的处置惩罚方法。
jQuery.fn.extend( {
toggleClass: function( value, stateVal ) {
var type = typeof value;
// 第二个参数为 boolean
if ( typeof stateVal === "boolean" && type === "string" ) {
return stateVal ? this.addClass( value ) : this.removeClass( value );
}
if ( jQuery.isFunction( value ) ) {
return this.each( function( i ) {
jQuery( this ).toggleClass(
value.call( this, i, getClass( this ), stateVal ),
stateVal
);
} );
}
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 ) || [];
while ( ( className = classNames[ i++ ] ) ) {
// 有则删,无则加,逻辑很简单
if ( self.hasClass( className ) ) {
self.removeClass( className );
} else {
self.addClass( className );
}
}
// 当无参或只要一个 false 时,一切 class 都实行
} else if ( value === undefined || type === "boolean" ) {
className = getClass( this );
if ( className ) {
// Store className if set
dataPriv.set( this, "__className__", className );
}
if ( this.setAttribute ) {
this.setAttribute( "class",
className || value === false ?
"" :
dataPriv.get( this, "__className__" ) || ""
);
}
}
} );
}
} );
看得出来,这个逻辑和前面两个很像,不过当无参或只要一个 boolean 且 false 时,先将当前的 className 保存到 data cache 中,然后完成 toggle 操纵:
if ( this.setAttribute ) {
this.setAttribute( "class",
className || value === false ? // 推断前提
"" : // 有则设空
dataPriv.get( this, "__className__" ) || "" // 无则从 data cache 取
);
}
总结
觉得 jQuery 中的 class 操纵不是很庞杂,岂非是我在提高吗,哈哈。
参考
jQuery 2.0.3 源码剖析 款式操纵
Selecting and manipulating CSS ..
.toggleClass()
本文在 github 上的源码地点,欢迎来 star。
欢迎来我的博客交换。