首頁 > web前端 > js教程 > 主體

jquery中什麼時候使用attr(),什麼時候使用prop()?

伊谢尔伦
發布: 2017-06-17 13:43:21
原創
1478 人瀏覽過

有人給 Multiple Select 外掛程式 提了問題:

setSelects doesn't work in Firefox when using jquery 1.9.0  一直都在用 jQuery 1.8.3 的版本,沒有嘗試過 jQuery 1.9.0 的版本。

於是,開始調試程式碼,在1.9.0 的版本:

<input type="checkbox" />
<script>
    $(function() {
        $('input').click(function() {
            $(this).attr('checked');
        });
    });
</script>
登入後複製

點擊checkbox,結果都是undefined

而在1.8.3 的版本中,結果是checked 和undefined

到這裡,問題答案找到了,就是使用attr() 方法的問題,於是查看官方文檔, 才知道從jQuery 1.6 開始新增了一個方法prop(),但是一直都沒有使用過。

從中文意思看,兩者分別是取得/設定 attributes 和 properties 的方法,那麼為什麼還要增加 prop() 方法呢?

Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior.
登入後複製

因為在 jQuery 1.6 之前,使用 attr() 有時候會出現不一致的行為

那麼,什麼時候使用attr(),什麼時候使用prop()?

To retrieve and change DOM properties such as the checked, selected, or disabled state of form elements, use the .prop() method.
登入後複製

根據官方的建議:具有true 和false 兩個屬性的屬性,如checked, selected 或disabled 使用prop(),其他的使用attr()

到此,將attr('checked') 改成prop('checked') 即可修復提的issues 了。

等等,看似問題還沒真正解決,為什麼開頭範例中 jQuery 1.8.3 和 1.9.0 使用 attr() 會有所差別呢?

想知道他們的差別,最好的方法還是看他們的原始碼:

1.8.3 attr():

attr: function( elem, name, value, pass ) {    var ret, hooks, notxml,
        nType = elem.nodeType;    // don't get/set attributes on text, comment and attribute nodes
    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {        return;
    }    if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {        return jQuery( elem )[ name ]( value );
    }    // Fallback to prop when attributes are not supported
    if ( typeof elem.getAttribute === "undefined" ) {        return jQuery.prop( elem, name, value );
    }

    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );    // All attributes are lowercase
    // Grab necessary hook if one is defined
    if ( notxml ) {
        name = name.toLowerCase();
        hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
    }    if ( value !== undefined ) {        if ( value === null ) {
            jQuery.removeAttr( elem, name );            return;

        } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {            return ret;

        } else {
            elem.setAttribute( name, value + "" );            return value;
        }

    } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {        return ret;

    } else {

        ret = elem.getAttribute( name );        // Non-existent attributes return null, we normalize to undefined
        return ret === null ?
            undefined :
            ret;
    }
}
登入後複製

1.9.0 attr():

 attr: function( elem, name, value, pass ) {   
  var ret, hooks, notxml,
        nType = elem.nodeType;    
  // don't get/set attributes on text, comment and attribute nodes
    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {        
           return;
    }    
   if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {        
        return jQuery( elem )[ name ]( value );
    }    
        // Fallback to prop when attributes are not supported
    if ( typeof elem.getAttribute === "undefined" ) {       
         return jQuery.prop( elem, name, value );
    }

    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );    
   // All attributes are lowercase
    // Grab necessary hook if one is defined
    if ( notxml ) {
        name = name.toLowerCase();
        hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
    }    
   if ( value !== undefined ) {        
       if ( value === null ) {
            jQuery.removeAttr( elem, name );            
            return;

        } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {            
            return ret;

        } else {
            elem.setAttribute( name, value + "" );           
             return value;
        }

    } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {      
               return ret;

    } else {

        ret = elem.getAttribute( name );        
      // Non-existent attributes return null, we normalize to undefined
        return ret === null ?
            undefined :
            ret;
    }
}
登入後複製

1.8.3 和1.9.0 的prop() 是一樣的:

prop: function( elem, name, value ) {    
  var ret, hooks, notxml,
   nType = elem.nodeType;    
   // don't get/set properties on text, comment and attribute nodes
    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {        
    return;
    }

    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );    
    if ( notxml ) {        
    // Fix name and attach hooks
        name = jQuery.propFix[ name ] || name;
        hooks = jQuery.propHooks[ name ];
    }   
     if ( value !== undefined ) {        
         if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {           
          return ret;

        } else {            
        return ( elem[ name ] = value );
        }

    } else {        
       if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {            
       return ret;

        } else {            
        return elem[ name ];
        }
    }
}
登入後複製

首先,我们看下 attr() 和 prop() 的区别

attr() 里面,最关键的两行代码

elem.setAttribute( name, value + "" ); 
ret =  elem.getAttribute( name );
登入後複製

很明显的看出来,使用的 DOM 的 API setAttribute() 和 getAttribute() 方法操作的属性元素节点。

prop() 里面,最关键的两行代码

return ( elem[ name ] = value );return elem[ name ];
登入後複製

可以理解为 document.getElementById(el)[name] = value,这是转化成 element 的一个属性。

对比调试 1.9.0 和 1.8.3 的 attr() 方法,发现两者的区别在于

hooks.get( elem, name ))
登入後複製

返回的值不一样,具体的实现:

1.8.3 中

boolHook = {
    get: function( elem, name ) {        
    // Align boolean attributes with corresponding properties
        // Fall back to attribute presence where some booleans are not supported
        var attrNode,
            property = jQuery.prop( elem, name );        
            return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
            name.toLowerCase() :           
             undefined;
    }
}
登入後複製

1.9.0 中

boolHook = {    get: function( elem, name ) {       
 var
            // Use .prop to determine if this attribute is understood as boolean
            prop = jQuery.prop( elem, name ),          
              // Fetch it accordingly
            attr = typeof prop === "boolean" && elem.getAttribute( name ),
            detail = typeof prop === "boolean" ?

                getSetInput && getSetAttribute ?
                    attr != null :                   
                     // oldIE fabricates an empty string for missing boolean attributes
                    // and conflates checked/selected into attroperties
                    ruseDefault.test( name ) ?
                        elem[ jQuery.camelCase( "default-" + name ) ] :
                        !!attr :               
                         // fetch an attribute node for properties not recognized as boolean
                elem.getAttributeNode( name );       
                 return detail && detail.value !== false ?
            name.toLowerCase() :
            undefined;
    }
}
登入後複製

由此可见,1.9.0 开始不建议使用 attr() 来对具有 true 和 false 两个属性的属性进行操作了。

那么我们的结论是:

具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr(),具体见下表:

以上是jquery中什麼時候使用attr(),什麼時候使用prop()?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!