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

加油!

jquery源码解析:val方法和valHooks对象详解的更多相关文章

  1. jQuery 源码解析(三十) 动画模块 $.animate()详解

    jQuery的动画模块提供了包括隐藏显示动画.渐显渐隐动画.滑入划出动画,同时还支持构造复杂自定义动画,动画模块用到了之前讲解过的很多其它很多模块,例如队列.事件等等, $.animate()的用法如 ...

  2. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  3. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

  4. jQuery源码分析(九) 异步队列模块 Deferred 详解

    deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...

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

    本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function() ...

  6. JQuery源码解析(一)

    写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...

  7. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  8. equals()方法和hashCode()方法详解

    equals()方法和hashCode()方法详解 1. Object类中equals()方法源代码如下所示: /** * Object类中的equals()方法 */ public boolean ...

  9. ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解

    原文 ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 ...

随机推荐

  1. 新手C#int.Parse、int.TryParse的学习2018.08.04

    int.Parse()用于将字符串转换为32为int类型,但是在遇到非数字或者类似1.545这种小数的时候会报错,后来采用了int.TryParse,这个在转换后会判断是否可以正常转换,若不能,会返回 ...

  2. mybatis使用foreach进行批量插入和删除操作

    一.批量插入 1.mapper层 int insertBatchRoleUser(@Param("lists") List<RoleUser> lists);//@Pa ...

  3. Gcc对头文件与库文件的搜索路径

    一.简介 对头文件与库文件的搜索路径不太清楚,编译.运行时老碰到问题,ldd查看程序的链接时,总是出现unkown链接. 二.头文件 gcc 在编译时寻找所需要的头文件 : 1)搜寻会从-I开始 2) ...

  4. DataStage 七、在DS中使用配置文件分配资源

    DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 DataStage 三.配置ODBC Da ...

  5. 微信小程序进行地图导航使用地图功能

    之前我写过的文章当中,提过小程序的打包大小.所以特地去下载一个区域的地图的这种方法,是不存在的. 我用的导航主要使用的是应用外的导航,这篇文章可能对于非常熟悉小程序的小伙伴来说就是小case,所以只适 ...

  6. 分布式事务,EventBus 解决方案:CAP【中文文档】(转)

    出处:http://www.cnblogs.com/savorboard/p/cap-document.html 前言 很多同学想对CAP的机制以及用法等想有一个详细的了解,所以花了将近两周时间写了这 ...

  7. 苹果禁用UUID了,咋办?

    By now you have probably heard that Apple is deprecating support for attaining a UDID from an iOS de ...

  8. Google Tango初学者教程

    Getting Started with the Tango Java API In this tutorial, we'll go through setting up your build env ...

  9. struts2 动态Action

    1.java 2.struts.xml struts2.5,默认关闭动态Action,着色的是开启和使用动态action 3.JSP 小结:访问时,用!后跟方法名的方法,方法返回值----->r ...

  10. 面试经验之——HE集团,YZ科技

    上周去了HE集团面试,该集团是做车辆辅助驾驶系统的,最终目标瞄准的是自动驾驶,加上再之前在YZ科技的面试经验,有些关于车辆驾驶上的心得想聊聊. 首先说说两个企业的面试情况吧.YZ科技中的两个技术聊天都 ...