Home  >  Article  >  Web Front-end  >  When to use attr() and when to use prop() in jquery?

When to use attr() and when to use prop() in jquery?

伊谢尔伦
伊谢尔伦Original
2017-06-17 13:43:211478browse

Someone gave Multiple Select plug-in asked a question:

setSelects doesn't work in Firefox when using jquery 1.9.0 I have been using the jQuery 1.8.3 version and have not tried the jQuery 1.9.0 version.

So, start debugging code, in version 1.9.0:

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

Click the checkbox, The results are all undefined

In version 1.8.3, the results are checked and undefined

At this point, the answer to the question is found, which is the problem of using the attr() method, so check From the official documentation, I learned that a new method prop() has been added since jQuery 1.6, but it has never been used. From the Chinese meaning, they are methods to obtain/set attributes and properties respectively, so why do we need to add the prop() method?

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

Because before jQuery 1.6, using attr() sometimes had inconsistent

behavior

. So, when to use attr() and when to use prop()?

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

According to official recommendations:

Attributes with two

attributes of true and false, such as checked, selected or disabled use prop(), others use attr()At this point, change attr('checked') to prop('checked') to fix the issues mentioned.

Wait, it seems that the problem has not been really solved. Why is there a difference in the use of attr() in jQuery 1.8.3 and 1.9.0 in the first example?

If you want to know the difference between them, the best way is to look at their source code:

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;
    }
}

The prop() of 1.8.3 and 1.9.0 is the same:

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(),具体见下表:

The above is the detailed content of When to use attr() and when to use prop() in jquery?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn