Une pratique exemplaire autour de setAttribute
à la place de la notation attributaire point (.
) a-t-elle été développée?
Par exemple.:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
ou
myObj.className = "nameOfClass";
myObj.id = "someID";
Vous devez toujours utiliser le formulaire direct .attribute
(mais consultez le lien quirksmode ci-dessous) si vous souhaitez un accès par programmation en JavaScript. Il devrait gérer correctement les différents types d'attributs (pensez "onload").
Utilisez getAttribute
/setAttribute
lorsque vous souhaitez traiter le DOM tel quel (par exemple, texte littéral uniquement). Différents navigateurs confondent les deux. Voir Modes Quirks: compatibilité (in) attribut .
De Javascript: Le guide définitif , cela clarifie les choses. Il note que les objets HTMLElement d'un document HTML définissent des propriétés JS correspondant à tous les attributs HTML standard.
Il vous suffit donc d’utiliser setAttribute
pour les attributs non standard.
Exemple:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
Aucune des réponses précédentes n'est complète et la plupart contiennent de la désinformation.
Il existe trois manières d'accéder aux attributs d'un DOM Element en JavaScript. Tous les trois fonctionnent de manière fiable dans les navigateurs modernes tant que vous comprenez comment les utiliser.
element.attributes
Les éléments ont une propriété attributs qui renvoie un objet NamedNodeMap direct Attr . Les index de cette collection peuvent être différents parmi les navigateurs. Donc, la commande n'est pas garantie. NamedNodeMap
a des méthodes pour ajouter et supprimer des attributs (getNamedItem
et setNamedItem
, respectivement).
Notez que même si XML est explicitement sensible à la casse, la spécification DOM appelle les noms de chaîne à normaliser , de sorte que les noms transmis à getNamedItem
ne font réellement pas la différence entre les majuscules et les minuscules.
var div = document.getElementsByTagName('div')[0];
//you can look up specific attributes
var classAttr = div.attributes.getNamedItem('CLASS');
document.write('attributes.getNamedItem() Name: ' + classAttr.name + ' Value: ' + classAttr.value + '<br>');
//you can enumerate all defined attributes
for(var i = 0; i < div.attributes.length; i++) {
var attr = div.attributes[i];
document.write('attributes[] Name: ' + attr.name + ' Value: ' + attr.value + '<br>');
}
//create custom attribute
var customAttr = document.createAttribute('customTest');
customAttr.value = '567';
div.attributes.setNamedItem(customAttr);
//retreive custom attribute
customAttr = div.attributes.getNamedItem('customTest');
document.write('attributes.getNamedItem() Name: ' + customAttr.name + ' Value: ' + customAttr.value + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
element.getAttribute
& element.setAttribute
Ces méthodes existent directement sur Element
sans avoir besoin d'accéder à attributes
et à ses méthodes, mais exécutent les mêmes fonctions.
Encore une fois, notez que le nom de la chaîne ne respecte pas la casse.
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.getAttribute('class') + '<br>');
document.write('Name: ID Value: ' + div.getAttribute('ID') + '<br>');
document.write('Name: DATA-TEST Value: ' + div.getAttribute('DATA-TEST') + '<br>');
document.write('Name: nonStandard Value: ' + div.getAttribute('nonStandard') + '<br>');
//create custom attribute
div.setAttribute('customTest', '567');
//retreive custom attribute
document.write('Name: customTest Value: ' + div.getAttribute('customTest') + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
element.id
De nombreux attributs sont accessibles à l’aide de propriétés pratiques sur l’objet DOM. Les attributs existants dépendent du type du nœud DOM et non des attributs définis dans le code HTML. Les propriétés sont définies quelque part dans la chaîne de prototypes d'objet DOM en question. Les propriétés spécifiques définies dépendront du type d'élément auquel vous accédez. Par exemple, className
et id
sont définis sur Element
et existent sur tous les nœuds DOM qui sont des éléments (c.-à-d. Pas des nœuds de texte ou de commentaire). Mais value
est plus étroit. Il est défini sur HTMLInputElement
et peut ne pas exister sur d'autres éléments.
Notez que les propriétés JavaScript sont sensibles à la casse. Bien que la plupart des propriétés utilisent des minuscules, certaines sont camelCase. Il faut donc toujours vérifier les spécifications pour en être sûr.
Ce "graphique" capture une partie de la chaîne de prototypes pour ces objets DOM. Ce n'est même pas proche de terminer, mais il capture la structure globale.
____________Node___________
| | |
Element Text Comment
| |
HTMLElement SVGElement
| |
HTMLInputElement HTMLSpanElement
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.className + '<br>');
document.write('Name: id Value: ' + div.id + '<br>');
document.write('Name: ID Value: ' + div.ID + '<br>'); //undefined
document.write('Name: data-test Value: ' + div.dataset.test + '<br>'); //.dataset is a special case
document.write('Name: nonStandard Value: ' + div.nonStandard + '<br>'); //undefined
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
Avertissement: il s'agit d'une explication de la définition des spécifications HTML et de la gestion des attributs par les navigateurs modernes. Je n'ai pas essayé de gérer les limitations d'anciens navigateurs brisés. Si vous devez prendre en charge les anciens navigateurs, en plus de ces informations, vous devez savoir ce qui ne fonctionne pas dans ces navigateurs.
Un cas que j'ai trouvé où setAttribute
est nécessaire est lors du changement d'attributs ARIA, car il n'y a pas de propriétés correspondantes. Par exemple
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
Il n'y a pas de x.arialabel
ou quoi que ce soit du genre, vous devez donc utiliser setAttribute.
Edit: x ["aria-label"] ne fonctionne pas. Vous avez vraiment besoin de setAttribute.
x.getAttribute('aria-label')
null
x["aria-label"] = "Test"
"Test"
x.getAttribute('aria-label')
null
x.setAttribute('aria-label', 'Test2')
undefined
x["aria-label"]
"Test"
x.getAttribute('aria-label')
"Test2"
Ces réponses ne traitent pas vraiment de la grande confusion entre les attributs et . En outre, selon le prototype Javascript, vous pouvez parfois utiliser la propriété d'un élément pour accéder à un attribut, et parfois vous ne pouvez pas.
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é appelée presque tout ce que vous voulez dans HTMLElement
, mais elle n’a rien à faire avec le DOM (contenu de la page). La notation par points (.
) concerne les propriétés . Maintenant, il y a quelques propriétés spéciales qui sont mappées sur des attributs, et à ce moment-là ou en écrivant, il n'y en a que 4 qui sont garanties (plus sur cela plus tard).
Tous les HTMLElement
s incluent une propriété appelée attributes
. HTMLElement.attributes
est un objet en direct NamedNodeMap
qui se rapporte aux éléments du DOM. "Live" signifie que lorsque le nœud change dans le DOM, il change du côté JavaScript, et inversement. Les attributs DOM, dans ce cas, sont les nœuds en question. Une Node
a une propriété .nodeValue
que vous pouvez modifier. Les objets NamedNodeMap
ont une fonction appelée setNamedItem
où vous pouvez changer 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');
(la note latérale, NamedNodeMap
ne respecte pas la casse, donc vous pouvez également passer 'DIR'
);
Il y a une fonction similaire directement dans HTMLElement
où vous pouvez simplement appeler setAttribute
qui créera automatiquement un noeud s'il ne le fait pas. existe et définit la nodeValue
. Il existe également des attributs auxquels vous pouvez accéder directement en tant que propriétés dans HTMLElement
via des propriétés spéciales , tel que dir
. Voici un aperçu de ce à quoi il 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 || ''
}
Vous pouvez donc modifier les attributs dir
de 6 manières:
// 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
et className
avec la méthode # 6.
HTMLElement
a ces 4 propriétés spéciales. Certains éléments sont des classes étendues de HTMLElement
ont encore plus de propriétés mappées. Par exemple, HTMLAnchorElement
a HTMLAnchorElement.href
, HTMLAnchorElement.rel
et HTMLAnchorElement.target
. Mais méfiez-vous , si vous définissez ces propriétés sur des éléments qui ne possèdent pas ces propriétés spéciales (comme sur un HTMLTableElement
), les attributs ne sont pas modifiés et ils le sont. juste, 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 || ''
}
Maintenant le gros avertissement: Comme tous les objets Javascript , vous pouvez ajouter des propriétés personnalisées. Mais, cela ne changera rien sur le DOM. Tu peux 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 scénario de test jsperf pour montrer la différence: https://jsperf.com/set-attribute-comparison . Fondamentalement, dans l'ordre:
dir
, id
, className
).element.attributes.ATTRIBUTENAME.nodeValue =
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 un élément étendu 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()
.
"Quand utiliser setAttribute vs .attribute = en JavaScript?"
Une règle générale consiste à utiliser .attribute
et à vérifier si cela fonctionne sur le navigateur.
..Si cela fonctionne sur le navigateur, vous êtes prêt à partir.
..Si ce n'est pas le cas, utilisez .setAttribute(attribute, value)
au lieu de .attribute
pour cet attribut .
Rinçage-répéter pour tous les attributs.
Eh bien, si vous êtes paresseux, vous pouvez simplement utiliser .setAttribute
. Cela devrait fonctionner correctement sur la plupart des navigateurs. (Bien que les navigateurs prenant en charge .attribute
puissent l’optimiser mieux que .setAttribute(attribute, value)
.)
méthodes de définition des attributs (par exemple, classe) sur un élément: 1. el.className = chaîne 2. el.setAttribute ('classe', chaîne) 3. el.attributes.setNamedItem (objet) 4. el.setAttributeNode (noeud)
J'ai fait un test de référence simple ( ici )
et il semble que setAttributeNode soit environ 3 fois plus rapide que l’utilisation de setAttribute.
donc si les performances sont un problème - utilisez "setAttributeNode"
Cela ressemble à un cas où il est préférable d'utiliser setAttribute:
Dev.Opera - JavaScript efficace
var posElem = document.getElementById('animation');
var newStyle = 'background: ' + newBack + ';' +
'color: ' + newColor + ';' +
'border: ' + newBorder + ';';
if(typeof(posElem.style.cssText) != 'undefined') {
posElem.style.cssText = newStyle;
} else {
posElem.setAttribute('style', newStyle);
}