jQuery源码学习(1)——addClass
最近比较闲,寻思着学习下jQuery源码,看了好多博客,很多都讲的比较详细。jQuery虽然只有那么200多K,但内容却比较丰富,对于我这样一个js菜鸟,看起来相当吃力。骨头太大,只能化整为零,从简单的小块开始。
今天看了下class系列的方法,贴下来!可能网上已经有很多,就当做自己记录笔记吧,请勿喷饭!
//添加类 addClass: function( value ) { var classNames, i, l, elem, setClass, c, cl; //如果value是一个函数,则调用这个函数得到运算结果,然后再递归调用addClass if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call(this, j, this.className) ); }); } if ( value && typeof value === "string" ) { //得到传入的class数组 classNames = value.split( core_rspace ); //this表示调用此方法的jQuery对象,可能有多个 for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; //元素类型节点类型:元素element 1;属性attr 2;文本text 3;注释comments 8;文档document 9 //如果是元素节点 if ( elem.nodeType === 1 ) { //如果元素没有class并且classNames数组只有一个元素,则直接赋值 if ( !elem.className && classNames.length === 1 ) { elem.className = value; } else { setClass = " " + elem.className + " "; //循环添加要加入的class for ( c = 0, cl = classNames.length; c < cl; c++ ) { if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) { setClass += classNames[ c ] + " "; } } elem.className = jQuery.trim( setClass ); } } } } //返回获取的jQuery对象 return this; },
//删除指定的类 removeClass: function( value ) { var removes, className, elem, c, cl, i, l; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call(this, j, this.className) ); }); } if ( (value && typeof value === "string") || value === undefined ) { removes = ( value || "" ).split( core_rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 && elem.className ) { //获取当前元素的class(用空格替换制表符或回车符、换行符) className = (" " + elem.className + " ").replace( rclass, " " ); // loop over each item in the removal list for ( c = 0, cl = removes.length; c < cl; c++ ) { // Remove until there is nothing to remove, while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) { className = className.replace( " " + removes[ c ] + " " , " " ); } } //如果value为空,则直接去掉元素的所有class;否则使用处理后的className elem.className = value ? jQuery.trim( className ) : ""; } } } //大部分方法都是返回this,遍于进行链式操作 return this; },
//如果没有class则添加,如果有则删除 //如果stateVal设置为true,则添加样式;如果为false,则删除样式 toggleClass: function( value, stateVal ) { var type = typeof value, //判断stateVal是否为boolean类型 isBool = typeof stateVal === "boolean"; //value为function时递归调用 if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.split( core_rspace ); //如果className[ i++ ] 存在 while ( (className = classNames[ i++ ]) ) { // check each className given, space separated list //如果第二个参数是boolean类型,则将第二个参数赋值给state; //否则判断当前jQuery对象是否拥有className这个类,将判断结果取反,赋值给state state = isBool ? state : !self.hasClass( className ); //如果state为true,则将className赋值给self['addClass']; //如果state为false,则将className赋值为self['removeClass'],这里的self就是当前jQuery对象 self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // toggle whole className //如果className为空或者value为false,则直接清空对象的class; //否则将保存的_className赋值给当前对象的className this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); },
//判断某个对象(或一个对象集中的第一个对象)是否拥有某个class hasClass: function( selector ) { var className = " " + selector + " ", i = 0, l = this.length; for ( ; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { return true; } } return false; },