zoukankan      html  css  js  c++  java
  • jQuery attributes(下)

    前文对属性的设置、读取、删除方法做了分解,本文继续对jQuery attributes模块分解。

    jQuery.fn.addClass

    /************************************
     *    value: 字符串或者是函数,字符串可以通过空格分隔className
     */
    jQuery.fn.addClass = function( value ) {
        var classes, elem, cur, clazz, j,
            i = 0,
            len = this.length,
            proceed = typeof value === "string" && value;
    
        //如果value是函数
        if ( jQuery.isFunction( value ) ) {
            //则对所有元素迭代运行addClass
            return this.each(function( j ) {
                jQuery( this ).addClass( value.call( this, j, this.className ) );
            });
        }
    
        //如果value是字符串
        if ( proceed ) {
            // 对value字符串分割成数组
            classes = ( value || "" ).match( core_rnotwhite ) || [];
    
            //遍历元素
            for ( ; i < len; i++ ) {
                elem = this[ i ];
                //如果节点是元素,则获取原来的className
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :    //替换掉换行符制表符等
                    " "
                );
    
                //如果cur不为false,即节点是元素
                if ( cur ) {
                    j = 0;
                    //遍历classes组装成新的className应有的值
                    while ( (clazz = classes[j++]) ) {
                        if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                            cur += clazz + " ";
                        }
                    }
                    //对className赋值,去掉头尾空白
                    elem.className = jQuery.trim( cur );
    
                }
            }
        }
    
        return this;
    };

    添加class的实现上还是比较简单的,利用elem.className来赋值。需要注意:

    var rclass = /[\t\r\n]/g;

    jQuery.fn.removeClass

    jQuery.fn.removeClass = function( value ) {
        var classes, elem, cur, clazz, j,
            i = 0,
            len = this.length,
            //参数是否正确
            proceed = arguments.length === 0 || typeof value === "string" && value;
    
        //如果value是函数
        if ( jQuery.isFunction( value ) ) {
            //则对所有元素迭代运行removeClass
            return this.each(function( j ) {
                jQuery( this ).removeClass( value.call( this, j, this.className ) );
            });
        }
        
        //如果参数正确
        if ( proceed ) {
            //分隔value成为class字符串数组
            classes = ( value || "" ).match( core_rnotwhite ) || [];
    
            //遍历
            for ( ; i < len; i++ ) {
                elem = this[ i ];
                // 获取className并进行预处理
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :
                    ""
                );
    
                //如果是元素
                if ( cur ) {
                    j = 0;
                    //遍历所有class字符串
                    while ( (clazz = classes[j++]) ) {
                        // 寻找是否有对应的字符串
                        while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
                            //有则去掉
                            cur = cur.replace( " " + clazz + " ", " " );
                        }
                    }
                    //给className赋值,并去掉头尾空格
                    elem.className = value ? jQuery.trim( cur ) : "";
                }
            }
        }
    
        return this;
    };

    删除class的实现和addClass非常像,只是通过indexOf和replace来替换掉需要删除的class。

    jQuery.fn.toggleClass

    jQuery.fn.toggleClass = function( value, stateVal ) {
        var type = typeof value,
            isBool = typeof stateVal === "boolean";
    
        //(⊙o⊙)…不说了,大家懂得
        if ( jQuery.isFunction( value ) ) {
            return this.each(function( i ) {
                jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
            });
        }
    
        //遍历所有元素
        return this.each(function() {
            //如果value是字符串
            if ( type === "string" ) {
                var className,
                    i = 0,
                    self = jQuery( this ),
                    state = stateVal,
                    //将value转成classNames字符串数组
                    classNames = value.match( core_rnotwhite ) || [];
    
                //遍历
                while ( (className = classNames[ i++ ]) ) {
                    //stateVal是布尔量,则直接设置为stateVal,否则判断元素是否不存在该className
                    state = isBool ? state : !self.hasClass( className );
                    //如果该className不存在则添加,否则删除
                    self[ state ? "addClass" : "removeClass" ]( className );
                }
    
            // 如果value的类型是undefined或者boolean
            } else if ( type === "undefined" || type === "boolean" ) {
                //如果元素的className存在
                if ( this.className ) {
                    // 将其存入缓存
                    jQuery._data( this, "__className__", this.className );
                }
    
                //对className赋值,为空或者缓存中的值
                this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
            }
        });
    };

    为了实现jQuery.fn.toggleClass还是花了很大功夫的。

    缓存的利用使得toggleClass操作更加方便,而不需要记录以前是那些class。

    jQuery.fn.hasClass

    jQuery.fn.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;
    };

    这个函数通过indexOf来寻找className是否存在。

    jQuery.fn.val

    jQuery.fn.val = function( value ) {
        var hooks, ret, isFunction,
            elem = this[0];
    
        //如果没有参数
        if ( !arguments.length ) {
            //如果元素存在
            if ( elem ) {
                //得到相应的钩子
                hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
    
                //通过钩子来得到值
                if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
                    return ret;
                }
    
                //如果没得到钩子,则通过elem.value来返回值
                ret = elem.value;
    
                //如果ret是字符串
                return typeof ret === "string" ?
                    // 将回车符替换
                    ret.replace(rreturn, "") :
                    // 如果ret是空的,则返回"",否则返回ret
                    ret == null ? "" : ret;
            }
    
            return;
        }
    
        //value是否是函数
        isFunction = jQuery.isFunction( value );
    
        //遍历所有元素
        return this.each(function( i ) {
            var val,
                self = jQuery(this);
    
            if ( this.nodeType !== 1 ) {
                return;
            }
    
            //如果value是函数,则转成参数
            if ( isFunction ) {
                val = value.call( this, i, self.val() );
            } else {
                val = value;
            }
    
            // 将null/undefined当成""
            if ( val == null ) {
                val = "";
            // 将数字转成字符串
            } else if ( typeof val === "number" ) {
                val += "";
            //如果是数组,则遍历数组
            } else if ( jQuery.isArray( val ) ) {
                val = jQuery.map(val, function ( value ) {
                    return value == null ? "" : value + "";
                });
            }
    
            //获取相应钩子
            hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
    
            // 如果钩子无法设置,则使用通常的设置方法
            if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
                this.value = val;
            }
        });
    };
  • 相关阅读:
    LeetCode 461. Hamming Distance
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode Find the Difference
    LeetCode 415. Add Strings
    LeetCode 445. Add Two Numbers II
    LeetCode 438. Find All Anagrams in a String
    LeetCode 463. Island Perimeter
    LeetCode 362. Design Hit Counter
    LeetCode 359. Logger Rate Limiter
  • 原文地址:https://www.cnblogs.com/justany/p/2867800.html
Copyright © 2011-2022 走看看