通过阅读jQuery为属性操作封装的基本方法和为处理兼容性问题提供的hooks,发现jQuery在属性操作方面并没有做过多的设计,只是处理一下兼容性问题,然后调用基础的DOM操作方法。以下是对JQuery提供的基础方法的阅读:

jQuery.fn.extend({

  // 调用access方法进行参数整理之后调用$.attr方法
    attr: function( name, value ) {
        return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
    },
  // 遍历jQuery对象中的所有元素,对每一个元素调用$.removeAttr方法
    removeAttr: function( name ) {
        return this.each(function() {
            jQuery.removeAttr( this, name );
        });
    },
  // 调用access方法进行参数整理之后调用$.attr方法
    prop: function( name, value ) {
        return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
    },
  // 遍历jQuery对象中的所有元素,直接删除该元素的相应属性
    removeProp: function( name ) {
        return this.each(function() {

    // 对html上的属性和DOM属性进行一些匹配转换
            delete this[ jQuery.propFix[ name ] || name ];
        });
    },
  
    addClass: function( value ) {
        var classes, elem, cur, clazz, j,
            i = 0,
            len = this.length,
            proceed = typeof value === "string" && value;
   // 如果value是function。
        if ( jQuery.isFunction( value ) ) {
            return this.each(function( j ) {

      // 执行该function并将结果作为参数再次调用addClass
                jQuery( this ).addClass( value.call( this, j, this.className ) );
            });
        }
   // 如果value是字符串
        if ( proceed ) {
            // 如果字符串中有空格,说明添加的不只是一个class,用空格将字符串转换成数组
            classes = ( value || "" ).match( core_rnotwhite ) || [];
     // 遍历jQuery中的每一个DOM元素
            for ( ; i < len; i++ ) {

      // 拿到当前元素
                elem = this[ i ];

      // 拿到当前元素上的所有当前class
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :
                    " "
                );
      // 如果是元素节点(这里看起来像是判断该元素是不是已经有class,其实只是判断是不是元素节点)
                if ( cur ) {
                    j = 0;

       // 遍历用户传入的所有class
                    while ( (clazz = classes[j++]) ) {

         // 如果当前元素已经有的class中没有用户传入的class,则在已经有的class中增加用户传入的class
                        if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                            cur += clazz + " ";
                        }
                    }

       // 删除最后得到的class字符串前后两端的空格之后赋值给当前元素的className属性
                    elem.className = jQuery.trim( cur );

}
            }
        }

   // 为了实现链式操作,返回this
        return this;
    },
  // 删除class和增加class的逻辑基本一致
    removeClass: function( value ) {
        var classes, elem, cur, clazz, j,
            i = 0,
            len = this.length,
            proceed = arguments.length === 0 || typeof value === "string" && value;

if ( jQuery.isFunction( value ) ) {
            return this.each(function( j ) {
                jQuery( this ).removeClass( value.call( this, j, this.className ) );
            });
        }
        if ( proceed ) {
            classes = ( value || "" ).match( core_rnotwhite ) || [];
            for ( ; i < len; i++ ) {
                elem = this[ i ];
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :
                    ""
                );
                if ( cur ) {
                    j = 0;
                    while ( (clazz = classes[j++]) ) {
                        // 只有此处不同,是从已经有的class中删除用户传入的class
                        while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
                            cur = cur.replace( " " + clazz + " ", " " );
                        }
                    }
                    elem.className = value ? jQuery.trim( cur ) : "";
                }
            }
        }

return this;
    },
  // toggleClass是通过调用addClass和removeClass来实现的。 
    toggleClass: function( value, stateVal ) {
        var type = typeof value;
   // stateval是一个boolean值,当为true时,发挥addClass的作用,当为false时,发挥removeClass的作用
        if ( typeof stateVal === "boolean" && type === "string" ) {
            return stateVal ? this.addClass( value ) : this.removeClass( value );
        }
   // 如果是个function,执行之后结果作为参数继续调用toggleClass
        if ( jQuery.isFunction( value ) ) {
            return this.each(function( i ) {
                jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
            });
        }
   // toggleClass的主体部分
        return this.each(function() {
            if ( type === "string" ) {
                var className,
                    i = 0,
                    self = jQuery( this ),
                    classNames = value.match( core_rnotwhite ) || [];
      // 遍历所有用户传入的class
                while ( (className = classNames[ i++ ]) ) {

         // 调用hasClass方法,如果有这个class就删除
                    if ( self.hasClass( className ) ) {
                        self.removeClass( className );

       // 如果没有就添加
                    } else {
                        self.addClass( className );
                    }
                }
    // 如果用户在调用toggleClass时没有传入class,则对已经有的所有class进行toggle
            } else if ( type === core_strundefined || type === "boolean" ) {
                if ( this.className ) {
                    // 当删除class时,为了能够在添加回来,将其储存到jQuery内部使用的data对象中
                    data_priv.set( this, "__className__", this.className );
                }

      // 如果当前元素有class或者没有value(说明没有传value,而是传入了stateVal,这个时候是想要删除class),清空className,否则从缓存中拿出来添      // 加给className属性
                this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
            }
        });
    },
    hasClass: function( selector ) {
        var className = " " + selector + " ",
            i = 0,
            l = this.length;
        for ( ; i < l; i++ ) {

     // 如果是元素节点,替换掉空格、空行等之后看是否存在用户传入的class
            if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {

      // 如果有,返回true
                return true;
            }
        }
   // 默认false
        return false;
    },
  // 得到或删除元素值
    val: function( value ) {
        var hooks, ret, isFunction,

     // 只对第一个元素进行操作
            elem = this[0];
     // 如果没有参数,则说明是要取元素值
        if ( !arguments.length ) {
            if ( elem ) {

      // 看看该元素是否有对应的hooks
                hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
      // 如果有对应的hooks,并且hooks中有get方法,则调用get方法。如果get方法返回了不是undefined的值,则返回该值。
                if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
                    return ret;
                }
      // 如果不存在hooks,则正常处理,直接拿到元素的value
                ret = elem.value;
                return typeof ret === "string" ?
                    ret.replace(rreturn, "") :
                    ret == null ? "" : ret;
            }
            return;
        }
   // 看参数是否是function
        isFunction = jQuery.isFunction( value );
   // 处理有参数的情况(设置元素值)
        return this.each(function( i ) {
            var val;
    // 如果不是元素节点,直接返回
            if ( this.nodeType !== 1 ) {
                return;
            }
    // 如果是function,将执行结果赋值个val
            if ( isFunction ) {
                val = value.call( this, i, jQuery( this ).val() );
            } else {
                val = value;
            }

    // 如果val为null,则赋值为空字符串
            if ( val == null ) {
                val = "";

    // 如果是number,转换成字符串
            } else if ( typeof val === "number" ) {
                val += "";

    // 如果是数组,呃。。
            } else if ( jQuery.isArray( val ) ) {
                val = jQuery.map(val, function ( value ) {
                    return value == null ? "" : value + "";
                });
            }
    // 看是否有对应的hooks
            hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
    // 如果没有对应的hooks,或者hooks中没有set方法,或者执行hooks的set方法返回的是undefined(这里其实默默的执行了hooks的set方法)
            if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {

      // 正常赋值
                this.value = val;
            }
        });
    }
});

jQuery属性操作(四)的更多相关文章

  1. jquery——属性操作、特殊效果

    1. attr().prop() 取出或者设置某个属性的值 <!DOCTYPE html> <html lang="en"> <head> &l ...

  2. jQuery源代码学习之八——jQuery属性操作模块

    一.jQuery属性模块整体介绍 jQuery的属性操作模块分四个部分:html属性操作,dom属性操作,类样式操作,和值操作. html属性操作(setAttribute/getAttribute) ...

  3. python全栈开发day48-jqurey自定义动画,jQuery属性操作,jQuery的文档操作,jQuery中的ajax

    一.昨日内容回顾 1.jQuery初识 1).使用jQuery而非JS的六大理由 2).jQuery对象和js对象转换 3).jQuery的两大特点 4).jQuery的入口函数三大写法 5).jQu ...

  4. jQuery属性操作

    jQuery 的属性操作的核心部分其实就是对底层 getAttribute().setAttributes()等方法的一系列兼容性处理 ...if ( notxml ) { name = name.t ...

  5. jQuery 属性操作和CSS 操作

    如有在jQuery方法中涉及到函数,此函数必定会返回一个数值(函数由于运行次数不同触发一些不同效果) jQuery 属性操作方法(以下方法前些日子学习过,不再赘述) addClass() attr() ...

  6. jQuery属性操作(二)

    挂载到$上的几个属性操作方法分析,发现属性操作用到了sizzle封装的方法 attr: function( elem, name, value ) {        var hooks, ret,   ...

  7. jQuery属性操作(一)

    下载了jQuery的UI组件,发现内容还挺多的,还是决定先把jQuery的源码看完一遍之后再涉足UI组件.考虑到队列和动画使用较少,特别是动画,基本开始使用css3完成.因此暂时略过,开始看jQuer ...

  8. web前端----jQuery属性操作

    知识点总结 1.属性 属性(如果你的选择器选出了多个对象,那么默认只会返回出第一个属性). attr(属性名|属性值) - 一个参数是获取属性的值,两个参数是设置属性值 - 点击加载图片示例 remo ...

  9. Jquery属性操作(入门二)

    ********JQuery属性相关的操作******** 1.属性 属性(如果你的选择器选出了多个对象,那么默认只会返回出第一个属性). attr(属性名|属性值) - 一个参数是获取属性的值,两个 ...

随机推荐

  1. HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)

    题目地址:pid=5067">HDU 5067 经典的TSP旅行商问题模型. 状压DP. 先分别预处理出来每两个石子堆的距离.然后将题目转化成10个城市每一个城市至少经过一次的最短时间 ...

  2. Android开源库项目集锦

    一.兼容类库 ActionBarSherlock : Action Bar是Android 3.0后才開始支持的,ActionBarSherlock是让Action Bar功能支持2.X后的全部平台. ...

  3. Java Decompiler Plugin For Eclipse IDE

    1. 下载JAD , 1.5.8版本的jad在 http://www.softpedia.com/progDownload/JAD-Download-85911.html 将展开后的jad.exe放到 ...

  4. Linux下设置SSH Server设置时间链接限制

    OpenSSH基于安全的理由,如果用户连线到SSH Server后闲置一段时间,SSH Server会在超过特定时间后自动终止SSH连线.本人习惯长时间连接,需要做如下修改: 1.打开ssh配置文件: ...

  5. css 阻止元素中的文本。双击选中

    //firefox -moz-user-select: none; //chrome.safari -webkit-user-select: none; //ie -ms-user-select: n ...

  6. android studio怎么导入appcompat-v7

    方法1: 在项目的build.gradle文件里,用传统的自动依赖处理方式:compile ‘com.Android.support:appcompat-v7:+’,然后rebuild就可以了. 方法 ...

  7. EJB的魅惑来源

      有人发帖子问学习EJB有个屁用啊?看完下面一个简单的介绍,也许你对EJB很感兴趣,它的优点极具魅惑力. 一.EJB是基于组件的开发. 利用Enterprise JavaBean,你就能像搭积木一样 ...

  8. 查看cp进度,使用watch

    watch -n 1 -d du -sh dir 每隔1s查看当前目录所占空间大小

  9. Http Cookie Manager、session

     1. JMeter Http Cookie Manager的作用: (1)自动管理 (2)象浏览器一样的存储和发送Cookie.如果你请求一个站点,然后他的Response中包含Cookie,Coo ...

  10. python中的字符串常量,是否支持通过下标的方式赋值

    说明: 今天在看python,通过下标获取字符串常量的字符,在想是否可以通过下标的方式赋值. 操作: 1.对字符串下标赋值 >>> text='python' >>> ...