jquery源码解析:jQuery对元素属性的操作3

这一课,我们将讲解val方法,以及对value属性的兼容性处理,jQuery中通过valHooks对象来处理。

首先,我们先来看下val方法的使用:

$("#input1").val()      //获取input元素的value属性值

$("#input1").val("hello")      //设置input元素的value属性值为hello。

然后我们来看一下val方法的源码:

jQuery.fn.extend({

  ......

  val: function( value ) {
    var hooks, ret, isFunction,
      elem = this[0];

    if ( !arguments.length ) {   //如果是获取操作,也就是参数为0时.
      if ( elem ) {
        hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

        //valHooks有以下几个属性对象:option(下拉框的子选项),select(下拉框),radio(单选按钮),checkbox(复选按钮)。也就意味着需要对这四种元素进行兼容性处理。其中radio的type=radio,checkbox的type=checkbox,select的type,默认为select-one(单选),还可以设置成select-multiple(<select multiple><option></option></select>,多选)。

        if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
          return ret;
        }

        ret = elem.value;

        return typeof ret === "string" ? ret.replace(rreturn, "") : ret == null ? "" : ret;
      }

      return;
    }

    isFunction = jQuery.isFunction( value );

    return this.each(function( i ) {  //设置操作,是针对每个元素
      var val;

      if ( this.nodeType !== 1 ) {  //必须是元素节点
        return;
      }

      if ( isFunction ) {
        val = value.call( this, i, jQuery( this ).val() );
      } else {
        val = value;
      }

      if ( val == null ) {  //针对这种情况:$("input").val(null);
        val = "";
      } else if ( typeof val === "number" ) {   //如果传入的是数字类型,就转换成字符串
        val += "";
      } else if ( jQuery.isArray( val ) ) {   //这里是针对checkbox,radio这种元素的,比如:$("#input2").val(["hello"]);这里如果传入的是字符串的话,是对checkbox的value属性赋值,但是传入数组,就代表checkbox的value是否等于hello,如果等于,就被选择上,如果不等于就不被选择上。
        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;
      }
    });
  }

});

jQuery.extend({
  valHooks: {
    option: {  //当你获取option元素的value属性值时,如果没有对此option显式设置value值,获取到的值是option的text,也就是option的文本。但是IE6-7下获取到的值是""。
      get: function( elem ) {
        var val = elem.attributes.value;   //在IE6-7下,val是一个object。
        return val.specified ? elem.value : elem.text;//如果val.specified为true,就代表value被显式设置了,因此直接返回elem.value,如果为false,就代表没有显式设置,因此返回elem.text。
      }
    },
    select: {
      get: function( elem ) {    //当select是单选时,获取的value值,就是你选择的那个option的值,如果是多选,获取值时,就是你选择的所有option的值的数组形式。
        var value, option,
          options = elem.options,   //select的所有option的集合。
            index = elem.selectedIndex,  //当前选择的option的索引值
              one = elem.type === "select-one" || index < 0,
                values = one ? null : [],   //如果是单选,values=null,如果是多选,values=[]。
                  max = one ? index + 1 : options.length,
                    i = index < 0 ? max : one ? index : 0;

        for ( ; i < max; i++ ) {   //单选,循环一次,多选,循环多次
          option = options[ i ];

          if ( ( option.selected || i === index ) &&   //IE6-9下,点击reset按钮时,option的selected不会恢复默认值,其他浏览器会恢复所有option的selected的默认值。

            ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&     //如果option被设置了disabled,那么获取option的值时,是获取不到的。
              ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {     //如果option的父元素被设置了disabled,并且父元素是optgroup,那么也获取不到。

            value = jQuery( option ).val();

            if ( one ) {
              return value;
            }

            values.push( value );
          }
        }

        return values;
      },

      set: function( elem, value ) {
        var optionSet, option,
          options = elem.options,
            values = jQuery.makeArray( value ),   //把value转换成数组
              i = options.length;

        while ( i-- ) {
          option = options[ i ];
          if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {  //判断select的子元素option的value是否在values数组中,如果在,就会把这个option选中。
            optionSet = true;
          }
        }

        if ( !optionSet ) {
          elem.selectedIndex = -1;  //如果select下的option的value值没有一个等于value的,那么就让select的选择索引值赋为-1.让select框中没有任何值。
        }
        return values;
      }
    }
  }

})

jQuery.each([ "radio", "checkbox" ], function() {
  jQuery.valHooks[ this ] = {
    set: function( elem, value ) {
      if ( jQuery.isArray( value ) ) {    //当value是数组时,看此元素的value值是否在数组value中,如果在就让元素被选择上。此元素只有radio,checkbox这两种。

        return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
      }
    }
  };
  if ( !jQuery.support.checkOn ) {   //如果元素是radio或者checkbox,我们去获取它的默认value值时,老版本webkit得到的值是"",而其他浏览器是on,因此当没有对此元素显式设置它的value值时(通过getAttribute获取的value的是null),我们通过input.value获取它的默认值,所有浏览器都返回on。
    jQuery.valHooks[ this ].get = function( elem ) {
      return elem.getAttribute("value") === null ? "on" : elem.value;
    };
  }
});

兼容处理,在jQuery中叫做hooks。针对不同的兼容处理,有不同的hooks来处理。比如:value值,就有valHooks,属性值,就有attrHooks,propHooks等。

加油!

时间: 2024-10-13 05:37:18

jquery源码解析:jQuery对元素属性的操作3的相关文章

JQuery源码解析-JQuery的工具方法(5)

下面对最后这几个方法进行讲解. guid():唯一表示(内部) proxy():改变this指向 access(): 多功能值操作 now():当前时间 swap():css交换(内部) guid: 这个属性是对事件进行控制的,例如每次对dom元素进行绑定事件的时候,会通过这个属性进行绑定,这个属性每次自增,产生一个唯一的标示,所以对dom元素进行事件解绑等操作的时候,通过这个属性就可以找到. 源码: // A global GUID counter for objects guid: 1, p

JQuery源码解析-JQuery的工具方法(3)

这篇文章主要对下面这几个方法进行解释 error();抛出异常 parseHTML():解析节点 parseJSON():解析JSON parseXML:解析XML noop():空函数 globalEval():全局解析JS camelCase():转驼峰 nodeName():是否为指定节点(内部) error:方法: error方法的作用是抛出一个自定义异常,内部直接调用了原生解释的throw new Error error: function( msg ) { throw new Err

JQuery源码解析-JQuery的工具方法(2)

这篇对下面的方法进行讲解: isFunction():是否为函数 isArray():是否为数组 isWindow():是否为window isNumeric()是否为数字 type():判断数据类型 isPlainObject():是否为对象自变量 isEmptyObject():是否为空的对象 isFunction方法: 这个方法很简单,判断对象是否为函数,返回bool类型,看一下源码: // See test/unit/core.js for details concerning isFu

JQuery源码解析-JQuery的工具方法(4)

下面对这些方法进行讲解 each():遍历集合 trim():去前后空格 makeArray():类数组转换真数组 inArray():数组版indexOf merge():合并数组 grep():过滤新数组 map():映射新数组 each方法: each是遍历集合用的方法,也是一个加强版的循环操作.例如: var arr = { Name: 'jam', Age: 15 }; $.each(arr, function (key, val) { console.log(key + ":&quo

jQuery源码解析(jQuery对象的实例属性和方法)

1.记录版本号 以及 修正constructor指向 jquery: core_version, constructor: jQuery, 因为jQuery.prototype={ ... } 这种写法将自动生成的jQuery.prototype.constructor属性覆盖删除,所以需要重新修正(指向其构造函数 jQuery).2.init() 初始化方法: init()方法最终返回的是this -jQuery(其实是jQuery.prototype.init)方法的实例对象. 实例对象继承

五.jQuery源码解析之jQuery.extend(),jQuery.fn.extend()

给jQuery做过扩展或者制作过jQuery插件的人这两个方法东西可能不陌生.jQuery.extend([deep],target,object1,,object2...[objectN]) jQuery.fn.extend([deep],target,object1,,object2...[objectN])这两个属性都是用于合并两个或多个对象的属性到target对象.deep是布尔值,表示是否进行深度合并,默认是false,不执行深度合并.通过这种方式可以在jQuery或jQuery.fn

二.jQuery源码解析之构建jQuery之构建函数jQuery的7种用法

一:$(selectorStr[,限制范围]),接受一个选择器(符合jQuery规范的字符串),返回一个jQuery对象;二:$(htmlStr[,文档对象]),$(html[,json对象])传入html字符串,创建一个新的dom元素 三:$(dom元素),$(dom元素集合)将dom元素转换成jQuery对象.四:$(自定义对象)封装普通对象为jQuery对象.五:$(回调函数)绑定ready事件监听函数,当Dom加载完成时执行.六:$(jQuery对象)接受一个jQuery对象,返回一个j

jquery源码解析:代码结构分析

本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function(){}; (96,283)   给jQuery对象添加一些属性和方法(实例方法,通过$("div")这类的jQuery实例对象来调用) (285,347)   extend : jQuery的继承方法 (349,817)   jQuery.extend():扩展一些工具方法(静态方法,直接通

十二.jQuery源码解析之.eq().first().last().slice()

eq(index):将集合中的索引为index的元素提取出来. first():返回集合中的第一个元素. .last():防护集合中的最后一个元素. .slice(start[,end]):返回集合中的给定区间段的元素. first()和last()调用eq(),eq()通过slice()实现,slice()通过 .pushStack()实现. 相关源码 285行:用法很奇特,通过一个"+"把可能为字符串的i转换成一个数值. 300~301:先借用数组方法slice()从当前jQuer

十一.jQuery源码解析之.pushStack()

pushStack()顾明思意,就是像桟中添加东西呗,现在看看他是如何添加东西的. 创建一个空的jQuery对象,然后把Dom元素集合放入这个jQuery对象中, 并保留对当前jQuery对象的引用. pushStack是核心方法之一,它为以下方法提供支持: jQuery对象遍历:.eq(),first(),.last(),.slice(),.map(); Dom查找,过滤:.find(),.not(),.filter(),.closest(),.add(),.andSelf(). Dom遍历: