jQuery source code analysis: detailed explanation of val method and valHooks object

In this lesson, we will explain the val method and the compatibility processing of the value attribute, which is handled by the valHooks object in jQuery.

First, let's look at the use of the val method:

$("#input1").val() //Get the value attribute value of the input element

$("#input1").val("hello") //Set the value attribute of the input element to hello.

Then let's take a look at the source code of the val method:

jQuery.fn.extend({

  ......

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

    if ( !arguments.length ) { //If it is an acquisition operation, that is, when the parameter is 0.
      if ( elem ) {         hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

        //valHooks has the following property objects: option (sub-option of the drop-down box), select (drop-down box), radio (radio button), checkbox (check button). This means that compatibility processing of these four elements is required. Among them, the type of radio=radio, the type of checkbox=checkbox, and the type of select, the default is select-one (single choice), and it can also be set to select-multiple (<select multiple><option></option></select> , multiple choice).

        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 ) { //setting operation is for each element
      var val;

      if ( this.nodeType !== 1 ) { // must be an element node
        return;
      }

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

      if ( val == null ) { //For this case: $("input").val(null);
        val = "";
      } else if ( typeof val === "number" ) { //If passed If the input is a number type, it will be converted to a string
        val += "";
      } else if ( jQuery.isArray( val ) ) { //This is for elements such as checkbox and radio, for example: $("#input2" ).val(["hello"]); Here, if a string is passed in, it is to assign a value to the value attribute of the checkbox, but if an array is passed in, it means whether the value of the checkbox is equal to hello, and if it is equal, it will be selected , if it is not equal, it will not be selected.
        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 ) { //Please see the code below to explain this.value
        = val;
      }
    } );
  }

});

jQuery.extend({   valHooks: {     option: { //When you get the value attribute value of the option element, if you do not explicitly set the value value for this option, the obtained value is the text of the option, that is, the text of the option. But the value obtained under IE6-7 is "".       get: function( elem ) {         var val = elem.attributes.value; //Under IE6-7, val is an object.         return val.specified ? elem.value : elem.text;//If val.specified is true, it means that the value is explicitly set, so elem.value is returned directly; if it is false, it means that it is not explicitly set, so elem.text is returned. }       }     ,     select: {       get: function( elem ) { //When the select is a single choice, the obtained value is the value of the option you selected. If it is a multi-selection, when the value is obtained, it is the value of all the options you selected Array form.         var value, option,           options = elem.options, //A collection of all options selected.             index = elem.selectedIndex, //The index value of the currently selected option












              one = elem.type === "select-one" || index < 0,
                values ​​= one ? null : [], //If single selection, values=null, if multiple selection, values=[].
                  max = one ? index + 1 : options. length,
                    i = index < 0 ? max : one ? index : 0;


        for ( ; i < max; i++ ) { //Single selection, cycle once, multiple selection, cycle multiple times
          option = options[ i ];

          if ( ( option.selected || i === index ) && //Under IE6-9, when the reset button is clicked, the selected value of the option will not restore the default value, and other browsers will restore the default value of the selected value of all options.

            ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && //If the option is set to disabled, the value of the option cannot be obtained.
              ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { //If the parent element of the option is set to disabled, and the parent element is optgroup, then it cannot be obtained.

            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 ), //convert value into an array               i = options.length;



        while ( i-- ) {           option = options[ i ];           if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ​​) >= 0) ) { //Judge the child element option of select Whether the value is in the values ​​array, if so, this option will be selected.             optionSet = true;           }         }




        if ( !optionSet ) {           elem.selectedIndex = -1; //If none of the option values ​​under select is equal to value, then assign the selection index value of select to -1. Let there be no value in the select box.         }         return values;       }     }   }





})

jQuery.each([ "radio", "checkbox" ], function() {   jQuery.valHooks[ this ] = {     set: function( elem, value ) {       if ( jQuery.isArray( value ) ) { //When value is When using an array, check to see if the value of this element is in the array value, and if so, let the element be selected. There are only two types of this element: radio and checkbox.


        return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } };
      if
    (
  !
  jQuery.support.checkOn ) { //If the element is radio or checkbox, we When getting its default value, the value obtained by the old version of webkit is "", while other browsers are on, so when the value of this element is not explicitly set (the value obtained through getAttribute is null) , we get its default value through input.value, and all browsers return on.
    jQuery.valHooks[ this ].get = function( elem ) {       return elem.getAttribute("value") === null ? "on" : elem.value;     };   } });



Compatibility processing is called hooks in jQuery. There are different hooks for different compatibility processing. For example: value value, there are valHooks, attribute value, there are attrHooks, propHooks, etc.

Guess you like

Origin blog.csdn.net/qq_18209847/article/details/84871353