Ces réponses n'abordent pas vraiment la grande confusion qui existe entre propriétés y attributs . De plus, selon le prototype Javascript, il est parfois possible d'utiliser la propriété d'un élément pour accéder à un attribut, parfois non.
Tout d'abord, vous devez vous rappeler qu'un HTMLElement
est un objet Javascript. Comme tous les objets, ils ont des propriétés. Bien sûr, vous pouvez créer une propriété portant le nom que vous voulez dans l'objet HTMLElement
mais il n'a rien à faire avec le DOM (ce qui se trouve sur la page). La notation par points ( .
) est pour propriétés . Maintenant, il y a certains spéciaux propriétés qui sont mappés à des attributs, et au moment où nous écrivons ces lignes, il n'y en a que 4 qui sont garantis (nous y reviendrons plus tard).
Tous HTMLElement
comprennent une propriété appelée attributes
. HTMLElement.attributes
es un en direct NamedNodeMap
Objet qui se rapporte aux éléments dans le DOM. "Live" signifie que lorsque le nœud change dans le DOM, il change du côté JavaScript, et vice versa. Les attributs DOM, dans ce cas, sont les nœuds en question. A Node
a un .nodeValue
que vous pouvez modifier. NamedNodeMap
ont une fonction appelée setNamedItem
où vous pouvez modifier le nœud entier. Vous pouvez également accéder directement au nœud par la clé. Par exemple, vous pouvez dire .attributes["dir"]
qui est identique à .attributes.getNamedItem('dir');
(Note complémentaire, NamedNodeMap
n'est pas sensible à la casse, donc vous pouvez également passer la commande 'DIR'
) ;
Il existe une fonction similaire directement dans HTMLElement
où vous pouvez simplement appeler setAttribute
qui créer automatiquement un nœud s'il n'existe pas et définir le nodeValue
. Il existe également un peu de auxquels vous pouvez accéder directement en tant que propriétés dans HTMLElement
via propriétés particulières tels que dir
. Voici une cartographie approximative de ce à quoi cela ressemble :
HTMLElement {
attributes: {
setNamedItem: function(attr, newAttr) {
this[attr] = newAttr;
},
getNamedItem: function(attr) {
return this[attr];
},
myAttribute1: {
nodeName: 'myAttribute1',
nodeValue: 'myNodeValue1'
},
myAttribute2: {
nodeName: 'myAttribute2',
nodeValue: 'myNodeValue2'
},
}
setAttribute: function(attr, value) {
let item = this.attributes.getNamedItem(attr);
if (!item) {
item = document.createAttribute(attr);
this.attributes.setNamedItem(attr, item);
}
item.nodeValue = value;
},
getAttribute: function(attr) {
return this.attributes[attr] && this.attributes[attr].nodeValue;
},
dir: // Special map to attributes.dir.nodeValue || ''
id: // Special map to attributes.id.nodeValue || ''
className: // Special map to attributes.class.nodeValue || ''
lang: // Special map to attributes.lang.nodeValue || ''
}
Donc vous pouvez changer le dir
attributs 6 façons :
// 1. Replace the node with setNamedItem
const newAttribute = document.createAttribute('dir');
newAttribute.nodeValue = 'rtl';
element.attributes.setNamedItem(newAttribute);
// 2. Replace the node by property name;
const newAttribute2 = document.createAttribute('dir');
newAttribute2.nodeValue = 'rtl';
element.attributes['dir'] = newAttribute2;
// OR
element.attributes.dir = newAttribute2;
// 3. Access node with getNamedItem and update nodeValue
// Attribute must already exist!!!
element.attributes.getNamedItem('dir').nodeValue = 'rtl';
// 4. Access node by property update nodeValue
// Attribute must already exist!!!
element.attributes['dir'].nodeValue = 'rtl';
// OR
element.attributes.dir.nodeValue = 'rtl';
// 5. use setAttribute()
element.setAttribute('dir', 'rtl');
// 6. use the UNIQUELY SPECIAL dir property
element["dir"] = 'rtl';
element.dir = 'rtl';
Vous pouvez mettre à jour toutes les propriétés avec les méthodes #1-5, mais seulement dir
, id
, lang
y className
avec la méthode n°6.
Extensions de HTMLElement
HTMLElement
possède ces 4 propriétés spéciales. Certains éléments sont des classes étendues de HTMLElement
ont des propriétés encore plus cartographiées. Par exemple, HTMLAnchorElement
tiene HTMLAnchorElement.href
, HTMLAnchorElement.rel
y HTMLAnchorElement.target
. Mais, attention Si vous définissez ces propriétés sur des éléments qui ne possèdent pas ces propriétés spéciales (par exemple, sur un élément HTMLTableElement
), les attributs ne sont pas modifiés et il s'agit simplement de propriétés personnalisées normales. Pour mieux comprendre, voici un exemple de son héritage :
HTMLAnchorElement extends HTMLElement {
// inherits all of HTMLElement
href: // Special map to attributes.href.nodeValue || ''
target: // Special map to attributes.target.nodeValue || ''
rel: // Special map to attributes.ref.nodeValue || ''
}
Propriétés personnalisées
Maintenant, le grand avertissement : Comme tous les objets Javascript vous pouvez ajouter des propriétés personnalisées. Mais, celles-ci ne changeront rien sur le DOM. Vous pouvez le faire :
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
Mais c'est la même chose que
newElement.myCustomDisplayAttribute = 'block';
Cela signifie que l'ajout d'une propriété personnalisée ne sera pas lié à .attributes[attr].nodeValue
.
Performance
J'ai construit un cas de test jsperf pour montrer la différence : https://jsperf.com/set-attribute-comparison . En gros, dans l'ordre :
- Les propriétés personnalisées car elles n'affectent pas le DOM et sont pas les attributs .
- Les mappages spéciaux fournis par le navigateur (
dir
, id
, className
).
-
Si les attributs existent déjà ,
element.attributes.ATTRIBUTENAME.nodeValue =
- setAttribute() ;
-
Si les attributs existent déjà ,
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
Conclusion (TL;DR)
-
Utilisez les mappages de propriétés spéciales de HTMLElement
: element.dir
, element.id
, element.className
ou element.lang
.
-
Si vous êtes sûr à 100% que l'élément est une extension HTMLElement
avec une propriété spéciale, utilisez ce mappage spécial. (Vous pouvez vérifier avec if (element instanceof HTMLAnchorElement)
).
-
Si vous êtes sûr à 100% que l'attribut existe déjà, utilisez element.attributes.ATTRIBUTENAME.nodeValue = newValue
.
-
Sinon, utilisez setAttribute()
.
7 votes
Quand je suis passé de
.setAttribute()
a[key] = value
tout a commencé à fonctionner comme par magie.