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;
    },

 

posted @ 2012-12-20 14:18  Vincent.Pei  阅读(390)  评论(0编辑  收藏  举报