2489 votes

.prop() vs .attr()

Alors jQuery 1.6 a la nouvelle fonction prop().

$(selector).click(function(){
    //au lieu de:
    this.getAttribute('style');
    //dois-je utiliser:
    $(this).prop('style');
    //ou:
    $(this).attr('style');
})

ou dans ce cas, est-ce qu'ils font la même chose?

Et si je dois passer à utiliser prop(), est-ce que tous les anciens appels à attr() vont casser si je passe à la version 1.6?

MISE À JOUR

selector = '#id'

$(selector).click(function() {
    //au lieu de:
    var getAtt = this.getAttribute('style');
    //dois-je utiliser:
    var thisProp = $(this).prop('style');
    //ou:
    var thisAttr = $(this).attr('style');

    console.log(getAtt, thisProp, thisAttr);
});

test

(voir aussi ce fiddle: http://jsfiddle.net/maniator/JpUF2/)

La console enregistre le getAttribute comme une chaîne, et le attr comme une chaîne, mais le prop comme une CSSStyleDeclaration, Pourquoi? Et comment cela affecte-t-il mon codage à l'avenir?

17 votes

Cela sera d'un intérêt certain : books.google.ca/…

29 votes

@Neal, c'est parce que ce changement va au-delà de jQuery. La différence entre les attributs HTML et les propriétés du DOM est énorme.

0 votes

@Matt mais qu'est-ce que attr retournait avant 1.6? est-ce que cela retournait toujours une chaîne de caractères?

1962voto

Tim Down Points 124501

Mise à jour du 1er novembre 2012

Ma réponse initiale s'applique spécifiquement à jQuery 1.6. Mon conseil reste le même mais jQuery 1.6.1 a légèrement modifié les choses : devant le nombre prévu de sites Web cassés, l'équipe jQuery a reverté attr() vers quelque chose de proche de (mais pas exactement identique à) son ancien comportement pour les attributs booléens. John Resig a également écrit à ce sujet sur son blog. Je comprends la difficulté dans laquelle ils se trouvaient mais je ne suis toujours pas d'accord avec sa recommandation de préférer attr().

Réponse originale

Si vous n'avez jamais utilisé directement le DOM mais seulement jQuery, ce changement pourrait être déroutant, bien qu'il soit certainement une amélioration conceptuelle. Moins bon pour les milliards de sites utilisant jQuery qui vont se casser en raison de ce changement cependant.

Je vais résumer les principaux problèmes :

  • Vous devriez généralement utiliser prop() plutôt que attr().
  • Dans la majorité des cas, prop() fait ce que attr() faisait auparavant. Remplacer les appels à attr() par prop() dans votre code fonctionnera généralement.
  • Les propriétés sont généralement plus simples à manipuler que les attributs. La valeur d'un attribut ne peut être qu'une chaîne alors qu'une propriété peut être de n'importe quel type. Par exemple, la propriété checked est un booléen, la propriété style est un objet avec des propriétés individuelles pour chaque style, la propriété size est un nombre.
  • Lorsqu'une propriété et un attribut portant le même nom existent, en général mettre à jour l'un mettra à jour l'autre, mais ce n'est pas le cas pour certains attributs des éléments de formulaire, comme value et checked : pour ces attributs, la propriété représente toujours l'état actuel tandis que l'attribut (sauf dans d'anciennes versions d'IE) correspond à la valeur/coché par défaut de l'élément (reflété dans la propriété defaultValue / defaultChecked).
  • Ce changement élimine une partie de la magie que jQuery plaçait devant les attributs et les propriétés, ce qui signifie que les développeurs jQuery devront en apprendre un peu plus sur la différence entre les propriétés et les attributs. C'est une bonne chose.

Si vous êtes un développeur jQuery et que vous êtes confus par toute cette affaire de propriétés et d'attributs, vous devez prendre du recul et en apprendre un peu à ce sujet, car jQuery ne cherche plus à vous protéger autant de ces choses. Pour des informations autorisées mais un peu arides sur le sujet, il y a les spécifications : DOM4, DOM HTML, DOM de niveau 2, DOM de niveau 3. La documentation du DOM de Mozilla est valable pour la plupart des navigateurs modernes et est plus facile à lire que les spécifications, vous pourriez donc trouver leur référence au DOM utile. Il y a une section sur les propriétés des éléments.

À titre d'exemple pour montrer que les propriétés sont plus simples à manipuler que les attributs, considérez une case à cocher qui est initialement cochée. Voici deux morceaux de code HTML valides pour faire cela :

Alors, comment savoir si la case à cocher est cochée avec jQuery ? Consultez Stack Overflow et vous trouverez généralement les suggestions suivantes :

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

C'est en fait la chose la plus simple au monde à faire avec la propriété booléenne checked, qui existe et fonctionne parfaitement dans tous les principaux navigateurs scriptables depuis 1995 :

if (document.getElementById("cb").checked) {...}

La propriété facilite également le fait de cocher ou décocher la case à cocher :

document.getElementById("cb").checked = false

Dans jQuery 1.6, cela devient de manière explicite

$("#cb").prop("checked", false)

L'idée d'utiliser l'attribut checked pour scripter une case à cocher est inutile et non nécessaire. La propriété est ce dont vous avez besoin.

  • Il n'est pas évident quelle est la manière correcte de cocher ou décocher la case à cocher en utilisant l'attribut checked
  • La valeur de l'attribut reflète la valeur par défaut plutôt que l'état visible actuel (sauf dans certaines anciennes versions d'IE, rendant les choses encore plus compliquées). L'attribut ne vous dit rien sur si la case à cocher sur la page est cochée. Voir http://jsfiddle.net/VktA6/49/.

0 votes

Donc si je veux mettre à niveau, je dois retourner en arrière et changer toutes les références de attr à prop ?

0 votes

@Neal: Oui, je soupçonne que cela fonctionnera dans la plupart des cas, bien que n'ayant pas étudié chaque partie du code jQuery attr() et prop(), je ne peux garantir que cela fonctionnera dans chaque cas.

0 votes

@TimDown, est-il donc plus facile de ramener un élément input à son état initial maintenant ?

695voto

T.J. Crowder Points 285826

Je pense que Tim l'a très bien dit, mais reculons un peu :

Un élément du DOM est un objet, une chose en mémoire. Comme la plupart des objets en POO, il a des propriétés. Il a également, séparément, une carte des attributs définis sur l'élément (généralement issus du balisage que le navigateur a lu pour créer l'élément). Certaines propriétés de l'élément obtiennent leurs valeurs initiales à partir des attributs ayant des noms identiques ou similaires (value obtient sa valeur initiale à partir de l'attribut "value"; href obtient sa valeur initiale à partir de l'attribut "href", mais ce n'est pas exactement la même valeur; className à partir de l'attribut "class"). D'autres propriétés obtiennent leurs valeurs initiales de différentes manières : Par exemple, la propriété parentNode obtient sa valeur en fonction de l'élément parent ; un élément a toujours une propriété style, qu'il ait un attribut "style" ou non.

Considérons cet ancre dans une page à http://example.com/testing.html :

Salut

Un peu d'art ASCII gratuit (et en laissant de côté beaucoup de choses) :

+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
|              HTMLAnchorElement             |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| href:        "http://example.com/foo.html" |
| name:        "fooAnchor"                   |
| id:          "fooAnchor"                   |
| className:   "test one"                    |
| attributes:  +−−−−−−−−−−−−−−

0 votes

Wow. cette nouvelle mise à jour 1.6.1 rend vraiment cette question un peu nulle.. (mais pas beaucoup) mais ce lien y répond pratiquement maintenant

0 votes

Il ne l'a pas annulé pour moi, j'ai simplement corrigé un bogue en utilisant jquery1.7 où je définissais .attr('class', 'bla') et cela ne fonctionnait pas alors que .prop('className', 'bla') fonctionnait

0 votes

@PandaWood: .attr('class', 'bla') fonctionne comme prévu pour moi dans 1.7.0, 1.7.1, et 1.7.2 sur Chrome 17, Firefox 11, Opera 11, IE6, IE8, IE9, et Safari 5.

258voto

Ce changement est depuis longtemps attendu pour jQuery. Pendant des années, ils se sont contentés d'une fonction appelée attr() qui était principalement utilisée pour récupérer des propriétés du DOM, et non le résultat auquel on s'attend en fonction du nom. La séparation de attr() et prop() devrait aider à dissiper une partie de la confusion entre les attributs HTML et les propriétés du DOM. $.fn.prop() récupère la propriété spécifiée du DOM, tandis que $.fn.attr() récupère l'attribut HTML spécifié.

Pour bien comprendre leur fonctionnement, voici une explication détaillée sur la différence entre les attributs HTML et les propriétés du DOM:

Attributs HTML

Syntaxe:

But: Permet au balisage d'avoir des données associées à des événements, au rendu et à d'autres fins.

Visualisation: Attributs HTML L'attribut class est montré ici sur le body. Il est accessible à travers le code suivant:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks et au-dessous
attr = document.body.getAttribute("className");

Les attributs sont retournés sous forme de chaîne de caractères et peuvent être différents d'un navigateur à l'autre. Cependant, ils peuvent être vitaux dans certaines situations. Comme illustré ci-dessus, le mode IE 8 Quirks (et inférieur) s'attend au nom d'une propriété du DOM dans get/set/removeAttribute au lieu du nom de l'attribut. C'est l'une des nombreuses raisons pour lesquelles il est important de connaître la différence.

Propriétés du DOM

Syntaxe:

document.body.onload = foo;

But: Donne accès aux propriétés appartenant aux nœuds d'éléments. Ces propriétés sont similaires aux attributs, mais ne sont accessibles qu'à travers JavaScript. C'est une différence importante qui aide à clarifier le rôle des propriétés du DOM. Veuillez noter que les attributs sont totalement différents des propriétés, car cet assignement de gestionnaire d'événement est inutile et ne recevra pas l'événement (le body n'a pas d'événement onload, seulement un attribut onload).

Visualisation: Propriétés du DOM

Ici, vous remarquerez une liste de propriétés sous l'onglet "DOM" dans Firebug. Ce sont des propriétés du DOM. Vous remarquerez immédiatement plusieurs d'entre elles, car vous les avez utilisées auparavant sans le savoir. Leurs valeurs sont ce que vous recevrez via JavaScript.

Documentation

Exemple

HTML:

JavaScript: alert($('#test').attr('value'));

Dans les versions antérieures de jQuery, cela renvoie une chaîne vide. Dans la version 1.6, elle renvoie la valeur correcte, foo.

Sans avoir regardé le nouveau code pour l'une ou l'autre fonction, je peux affirmer avec confiance que la confusion a davantage à voir avec la différence entre les attributs HTML et les propriétés du DOM, plutôt qu'avec le code lui-même. Espérons que cela vous a éclairci certaines choses.

-Matt

13 votes

$.prop() obtient les propriétés du DOM, $.attr() obtient les attributs HTML. J'essaie de combler le fossé psychologique pour que vous puissiez comprendre la différence entre les deux.

0 votes

@Matt, vous n'avez pas mentionné cela dans votre réponse... Pouvez-vous expliquer ce que prop() fait s'il vous plaît?

12 votes

Garçon, je suis aussi confus maintenant. Alors $('#test').prop('value') ne renvoie rien ? Ni .attr('checked') pour une case à cocher ? Mais ça le faisait avant ? Maintenant, il faudrait le changer en prop('checked') ? Je ne comprends pas le besoin de cette distinction - pourquoi est-il important de différencier entre les attributs HTML et les propriétés DOM ? Quel est le cas d'utilisation commun qui a rendu ce changement "attendu depuis longtemps" ? Qu'est-ce qui ne va pas avec l'abstraction de la distinction entre les deux, puisque leurs cas d'utilisation se chevauchent principalement ?

254voto

HerrSerker Points 9005

Une propriété est dans le DOM; un attribut est dans le HTML qui est analysé dans le DOM.

Détails supplémentaires

Si vous modifiez un attribut, le changement sera reflété dans le DOM (parfois avec un nom différent).

Exemple: Changer l'attribut class d'une balise modifiera la propriété className de cette balise dans le DOM (C'est parce que class est un mot réservé en JavaScript et ne peut pas être utilisé comme nom de propriété). Si vous n'avez pas d'attribut sur une balise, vous avez quand même la propriété DOM correspondante avec une valeur vide ou par défaut.

Exemple: Bien que votre balise n'ait pas d'attribut class, la propriété DOM className existe avec une valeur de chaîne vide.

éditer

Si vous modifiez l'un, l'autre sera modifié par un contrôleur, et vice versa. Ce contrôleur n'est pas dans jQuery, mais dans le code natif du navigateur.

0 votes

Est-ce que cela signifie qu'il vaut mieux mettre à jour l'attribut, car ainsi vous vous assurez que l'attribut et la propriété sont tous les deux mis à jour et sont alignés ?

1 votes

@Luke le DOM est une représentation technique interne, le modèle. Les attributs HTML sont une représentation externe, une vue. Si vous modifiez l'un, l'autre sera modifié par un contrôleur, et vice versa.

0 votes

@HerrSerker Donc ils restent synchronisés via un contrôleur ? Je suppose que c'est juste dans les méthodes attr et prop de jQuery ? Voici une modification de votre fiddle où j'explore cela plus en détail - jsfiddle.net/v8wRy - et jusqu'à présent, ils semblent équivalents.

145voto

Gary Hole Points 9736

C'est simplement la distinction entre les attributs HTML et les objets du DOM qui cause une confusion. Pour ceux qui sont à l'aise d'agir sur les propriétés natives des éléments du DOM comme this.src this.value this.checked, .prop est un accueil très chaleureux dans la famille. Pour d'autres, c'est juste une couche supplémentaire de confusion. Clarifions cela.

La manière la plus simple de voir la différence entre .attr et .prop est l'exemple suivant :

  1. $('input').attr('blah') : retourne 'hello' comme prévu. Pas de surprises ici.
  2. $('input').prop('blah') : retourne undefined -- car il essaie de faire [HTMLInputElement].blah -- et aucune telle propriété n'existe sur cet objet du DOM. Elle n'existe que dans la portée comme un attribut de cet élément c'est-à-dire [HTMLInputElement].getAttribute('blah')

Maintenant nous changeons quelques choses comme ceci :

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah') : retourne 'apple' hein ? Pourquoi pas "poire" puisque cela a été défini en dernier sur cet élément. Parce que la propriété a été modifiée sur l'attribut d'entrée, pas sur l'élément d'entrée du DOM lui-même -- ils fonctionnent essentiellement presque indépendamment l'un de l'autre.
  2. $('input').prop('blah') : retourne 'poire'

La chose à laquelle vous devez vraiment faire attention est simplement de ne pas mélanger l'utilisation de ces deux pour la même propriété dans toute votre application pour la raison ci-dessus.

Voir un exemple illustrant la différence : http://jsfiddle.net/garreh/uLQXc/


.attr vs .prop :

Round 1 : style

  • .attr('style') -- retourne les styles en ligne pour l'élément correspondant c'est-à-dire "font:arial;"
  • .prop('style') -- retourne un objet de déclaration de style c'est-à-dire CSSStyleDeclaration

Round 2 : value

$('input').prop('value', 'j'ai changé la valeur');
  • .attr('value') -- retourne 'hello' *
  • .prop('value') -- retourne 'j'ai changé la valeur'

* Remarque : jQuery, pour cette raison, a une méthode .val(), qui est équivalente en interne à .prop('value')

0 votes

@Neal car cela donne une référence à la structure des fonctions jQuery de manière plus claire. "$('input').prop('blah'): retourne indéfini -- car il essaie de faire [HTMLInputElement].blah -- et aucune propriété de cet objet DOM n'existe. Elle n'existe que dans le scope en tant qu'attribut de cet élément, c'est-à-dire [HTMLInputElement].getAttribute('blah')"

2 votes

Semble différent du doc, api.jquery.com/prop : "La méthode .prop() devrait être utilisée pour définir disabled et checked au lieu de la méthode .attr(). La méthode .val() devrait être utilisée pour obtenir et définir la valeur."

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X