jQuery 中 attr() 和 prop() 方法的區別<轉>

來源:互聯網
上載者:User

標籤:des   http   io   ar   os   使用   java   sp   for   

前幾天,有人給 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 ) {    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; } // 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 ); } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, value + "" ); return value; } } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { // In IE9+, Flash objects don‘t have .getAttribute (#12945) // Support: IE9+ if ( typeof elem.getAttribute !== "undefined" ) { 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() 方法的區別<轉>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.