zoukankan      html  css  js  c++  java
  • jquery源码解析:val方法和valHooks对象详解

    这一课,我们将讲解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等。

    加油!

  • 相关阅读:
    InstallShield2015制作安装包----------卸载前结束执行中的进程
    InstallShield2015制作安装包----------安装过程中修改文件内容
    InstallShield2015制作安装包----------卸载后删除安装目录和文件
    InstallShield2015制作安装包----------安装后实现自动运行
    snmp getTable demo :iftable ipAddresstable
    snmp
    Android Lazy url
    eclipse key
    demo16Toast
    demo15 AlertDialog
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4204760.html
Copyright © 2011-2022 走看看