Difference between ".attr ()" and ".data ()"

14

Note that there is a difference between updating or applying a data attribute using the jQuery method .attr() and the method .data() .

The examples below can be seen in this JSFiddle .

  • Apply value to non-existent attribute

    If you apply the value using the .attr() method and then change it using the .data() method, the result in collecting the value varies according to the method used to apply it:

    <div id="myBanana"></div>
    
    • Apply

      // utilizando .attr()
      $( "#myBanana" ).attr( "data-fail", "no banana" );
      
      // utilizando .data()
      $( "#myBanana" ).data( "fail", "no monkey" );
      
    • Collapse

      // utilizando .attr() da "no banana"
      console.log( $( "#myBanana" ).attr( "data-fail" ) );
      
      // utilizando .data() dá "no monkey"
      console.log ( $( "#myBanana" ).data( "fail" ) );
      
  • Apply value to existing attribute

    If the attribute already exists in the element, when collecting it with any of the methods, I get the existing value.

    After making a change to the value, depending on the method used, the applied value is only correctly collected if you use the same method to get it:

    <div id="myMonkey" data-fail="banana"></div>
    
    • Collapse

      // utilizando .attr() dá "banana"
      console.log( $( "#myMonkey" ).attr( "data-fail" ) );
      
      // utilizando .data() dá "banana"
      console.log ( $( "#myMonkey" ).data( "fail" ) );
      
    • Change

      // utilizando .attr()
      $( "#myMonkey" ).attr( "data-fail", "No banana" );
      
      // utilizando .data()
      $( "#myMonkey" ).data( "fail", "More banana" );
      
    • Retrace

      // utilizando .attr() dá "No banana"
      console.log( $( "#myMonkey" ).attr( "data-fail" ) );
      
      // utilizando .data() dá "More banana"
      console.log ( $( "#myMonkey" ).data( "fail" ) );
      

    At the start both methods were collecting the same value that was already present in the data attribute, but after changing this value, I have to use the same method to apply and collapse values or diverge results.

It is obvious that the fact that the attribute is called data-* is not directly related to the .data() method, but to the .attr() method.

In addition, both methods seem to interact with the data attribute to a certain extent, but each has its way of saving new assigned values.

In analyzing what happens in terms of manipulation of the DOM, there are also visible differences in substances caused by the use of each of the methods:

The .attr() method is actually updating the value of the data attribute while the .data() method does not affect the value of the attribute, rather it attaches an identifier with its value to the element.

Question

What is the difference between the .attr() method and the .data() method in terms of usage, purpose, and impact on the element, to make use of the arbitrary data assignment that HTML5 provides?

    
asked by anonymous 14.01.2014 / 18:38

2 answers

11

The two methods are completely different

.data()

.data() was created for the purpose of associating arbitrary data with a DOM element. In fact, this method is an interface to $.data , which is part of the jQuery core.

The data is stored in an internal object, and there it is associated with the DOM element in question. The data does not hang directly on the object that represents the element. This is very clear if you look at the source code . By consolidating the data- attributes in HTML5 *, .data() starts reading the HTML attribute if it does not find an equivalent key.

Therefore, do not consider .data as a method to deal with data- attributes. He is more than that. What's more, it has two fundamental differences (one of you pointed out in the question):

  • When writing data with .data() , the corresponding data- attribute is not affected
  • If the name of your attribute contains underscores or hyphens, .data() applies camelCase to the name before using it as the internal key.
  • .attr()

    .attr() is dedicated to working with attributes. It will always read from an attribute and write to an attribute, that is, modify the DOM, as opposed to .data() . Personally, it is my preferred method for dealing with data- attributes, especially for not changing the names with camelization as does .data() .

    * I'm not so sure about the chronology here

        
    14.01.2014 / 19:16
    7

    The main reason for this behavior was explained in @bfavaretto's answer (difference between arbitrary data maintained by jQuery and data-* attributes), but even though jQuery did nothing special with data , it still would not behave as expected.

    Quoting an answer in SOEN:

      

    A DOM element is an object, a thing in memory. Like most objects in the OOP, it has properties . It also, separately, has a mapping of the attributes defined in the element (usually coming from the markup that the browser has read to create the element). Some of the properties of the element earn their initial value from the attributes with the same name or similar name ( value gets its initial value attribute "value"; href gets its initial value from the "href" attribute, but is not exactly the same value; className of the "class" attribute). Other properties get their initial values in other ways: For example, the parentNode property gets its value based on what its parent element; an element always has a style property, regardless of whether it has a "style" attribute or not.

    Previous versions of jQuery mixed attributes with properties, resulting in strange behavior. From the 1.6 version, the attr method has been separated from prop (not without crashes on the course > ...), so that conceptually does not make much sense if you continue to use attr - since in the vast majority of cases what you want is prop . Until the 1.9 version, these two methods were still synchronized for compatibility reasons, but from then on they were separated from each other.

    Consider the following markup:

    <input value="foo">
    

    And the following JavaScript:

    $("input").prop("value", "propriedade");
    $("input").attr("value", "atributo");
    

    What will be the value of the text box at the end of execution? If you run this in jQuery 1.8, it will be "atributo" (since it was last assigned, and either use attr or prop ). If you use 1.9, it will be "propriedade" (since attr only changed the markup, the DOM object remained unchanged). Example 1 , Example 2 .

    So do not expect attr to stay updated as elements in the DOM change, use it only if you want to get the initial status of them (ie what was written in the markup ).

    Update: The behavior of .data today is very different from what I remembered. I've done some additional tests , and now I can understand how it works:

    • If there is no value assigned programmatically through the .data(chave, valor) method, then it uses the value of the data-chave attribute.
      • This applies both to the absence of the assignment and to the removal of this value.
    • If it exists, it uses the assigned value - ignoring the attribute.
    • There is no property data-chave , dataChave , etc.

    Example:

    <div id="teste" data-foo="10">
    
    $("#teste").data("foo"); // 10
    
    $("#teste").data("foo", 20);
    $("#teste").data("foo"); // 20
    
    $("#teste").attr("data-foo", 30);
    $("#teste").data("foo"); // ainda 20
    
    $("#teste").removeData("foo");
    $("#teste").data("foo"); // 30
    
        
    15.01.2014 / 02:21