zoukankan      html  css  js  c++  java
  • jQuery val()方法及valHooks源码解读

        val: function( value ) {
            var hooks, ret, isFunction,
                elem = this[0];
    
            if ( !arguments.length ) {//无参数
                if ( elem ) {//第一个元素
                    //考虑元素是checkbox,radio,option或者select的情况,这时有val钩子
                    hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
                    //如果钩子存在且有get 且获取的值不为undefined,返回该值
                    if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
                        return ret;
                    }
                    //否则,ret就是元素的value
                    ret = elem.value;
                    //如果值是字符串
                    return typeof ret === "string" ?
                        //将换行符替换为""
                        ret.replace(rreturn, "") :
                        // 如果值不是字符串,考虑null和undefined的情况,如果是null或undefined,ret置为""
                        ret == null ? "" : ret;
                }
    
                return;
            }
            //判断传入的参数value是否是函数
            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;
                }
    
                //如果val是null或者undefined,设为""
                if ( val == null ) {
                    val = "";
                //如果val是数字,转为字符串
                } else if ( typeof val === "number" ) {
                    val += "";
                //如果val是数组    
                } else if ( jQuery.isArray( val ) ) {//处理数组中的undefined null 和数字
                    val = jQuery.map( val, function( value ) {
                        return value == null ? "" : value + "";
                    });
                }
                //同样地,考虑元素是checkbox,radio,option或者select的情况
                hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
    
                // 如果set返回了undefined,回退到正常值val
                if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
                    this.value = val;
                }
            });
        }

    valHooks:

    jQuery.extend({
        valHooks: {
            option: {
                get: function( elem ) {
                    //调用Sizzle.attr方法
                    var val = jQuery.find.attr( elem, "value" );
                    //如果val为null或undefined,取elem的text值
                    return val != null ?
                        val :
                        // Support: IE10-11+
                        // option.text throws exceptions (#14686, #14858)
                        jQuery.trim( jQuery.text( elem ) );
                }
            },
            select: {
                get: function( elem ) {
                    var value, option,
                        options = elem.options,
                        index = elem.selectedIndex,//当前选中项 单选默认0,多选默认-1
                        //如果是单选下拉框或者当前没有选中项,one为true
                        one = elem.type === "select-one" || index < 0,
                        values = one ? null : [],//one为true,则values为null,否则为[]
                        max = one ? index + 1 : options.length,//单选最大为1,多选为options.length
                        i = index < 0 ?
                            max :
                            one ? index : 0;
    
                    // Loop through all the selected options
                    for ( ; i < max; i++ ) {//遍历
                        option = options[ i ];
    
                        // IE6-9 doesn't update selected after form reset (#2551)
                        if ( ( option.selected || i === index ) && //如果当前项是选中项
                                // Don't return options that are disabled or in a disabled optgroup
                                // 如果support.optDisabled为true,值为option.disabled取反
                                // 如果为假,值为option的属性disabled的值
                                // 如果值为null
                                ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
                                //且 如果select的disabled为假或者 optgroup的disabled为真
                                ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
    
                            // Get the specific value for the option
                            value = jQuery( option ).val();
    
                            // We don't need an array for one selects
                            if ( one ) {//单选直接返回
                                return value;
                            }
    
                            // Multi-Selects return an array
                            values.push( value );//多选推入数组
                        }
                    }
    
                    return values;//多选且没有没有默认项,不经过循环直接返回
                },
    
                set: function( elem, value ) {
                    var optionSet, option,
                        options = elem.options,
                        values = jQuery.makeArray( value ),//转为数组,value可以是任何值 "a"=>["a"]
                        i = options.length;//选项数量
                    //遍历
                    while ( i-- ) {
                        option = options[ i ];
                        //如果当前选项的值在values数组中,selected为true,否则为false
                        //可以用于设置多选的下拉单值
                        /*用法:
                            <select name="" id="" class="slt" multiple>
                                <option value="a">aaa</option>
                                <option value="b">bbbb</option>
                                <option value="c">ccccc</option>
                            </select>
                            <script>
                                $('.slt').val(["a","c"]);
                            </script>
                         */
                        if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
                            optionSet = true;//标识
                        }
                    }
    
                    // force browsers to behave consistently when non-matching value is set
                    if ( !optionSet ) {
                        elem.selectedIndex = -1;
                    }
                    return values;
                }
            }
        }
    });
    
    // Radios and checkboxes getter/setter
    jQuery.each([ "radio", "checkbox" ], function() {
        jQuery.valHooks[ this ] = {
            set: function( elem, value ) {
                if ( jQuery.isArray( value ) ) {
                //如果传入的value是数组,判断当前元素的值是否在value数组中
                //存在,则设置checked为true,并返回true,不存在则checked为false,并返回false
                /*
                    用法:
                    <input type="checkbox" class="ck" value="a">
                    <input type="checkbox" class="ck" value="b">
                    <script>
                        $('.ck').val(["a","b"]);
                    </script>    
                 */
                    return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
                }
            }
        };
        if ( !support.checkOn ) {
            jQuery.valHooks[ this ].get = function( elem ) {
                //如果未指定value,返回on
                //如果是 <input type="checkbox" class="ck" value>或者 
                //<input type="checkbox" class="ck" value="">这两种,返回的是""
                return elem.getAttribute("value") === null ? "on" : elem.value;
            };
        }
    });

    可以看到,jQ的valHooks共有四个成员:

    1、option

    2、select

    3、checkbox

    4、radio

    option中只有get方法,因为它的目的是在option中没有value值的时候去取中间的text值。

    checkbox和radio中,set方法是考虑到同时为多个复选或者单选框设置值的情况,而get方法是考虑了没有初始化value时返回默认值“on”

    select的set方法同复选单选框类似,而get方法中,如果是单选,直接返回value,如果是多选且有选中项,遍历后将结果推入数组最后返回数组,此外,它处理了option的disabled为true的情况,如果为true,获取不到值。这一点也是我的疑问,它为什么要这样做→ →

        <select name="" id="slt" class="slt">
            <option value="a">aaa</option>
            <option value="b">bbbb</option>
            <option value="c" selected disabled>ccccc</option>
        </select>
        <script>
        console.log($('#slt').val(),document.getElementById("slt").value);
        </script>
    // null "c"
  • 相关阅读:
    C#自己写的迭代器(拓展字典)
    C#中的浅复制和深复制
    C#中的委托和事件
    转载--《怎样制作一款优秀的塔防游戏》
    3D数学基础
    MonoBehaviour可重写的函数
    悲观锁及乐观锁
    java nio
    hadoop2.x通过Zookeeper来实现namenode的HA方案集群搭建-实践版
    oozie bundle学习笔记
  • 原文地址:https://www.cnblogs.com/qianlegeqian/p/4276734.html
Copyright © 2011-2022 走看看