jquery源碼解析:jQuery對元素屬性的操作3

來源:互聯網
上載者:User

標籤:

這一課,我們將講解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源碼解析:jQuery對元素屬性的操作3

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.