Antworten:
Sie sollten immer das direkte .attribute
Formular verwenden (siehe jedoch den Link zum Quirksmode unten), wenn Sie programmgesteuerten Zugriff in JavaScript wünschen. Es sollte die verschiedenen Arten von Attributen (denken Sie an "Onload") korrekt behandeln.
Verwenden Sie getAttribute
/, setAttribute
wenn Sie das DOM so behandeln möchten, wie es ist (z. B. nur wörtlicher Text). Verschiedene Browser verwechseln die beiden. Siehe Quirks-Modi: Attribut (in) -Kompatibilität .
Aus Javascript: The Definitive Guide , es klärt die Dinge. Es wird darauf hingewiesen, dass HTMLElement- Objekte eines HTML-Dokuments JS-Eigenschaften definieren, die allen Standard-HTML-Attributen entsprechen.
Sie müssen sie also nur setAttribute
für nicht standardmäßige Attribute verwenden.
Beispiel:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
node.frameborder
NICHT definiert wurde. Sie müssen also getAttribute erhalten, um den Wert zurückzugewinnen.
frameBorder
direkt einzustellen , aber beachten Sie die Großschreibung. Jemand hielt es für eine gute Idee, die JavaScript-Entsprechungen von HTML-Attributen zu camelCase. Ich habe es nicht geschafft, eine Spezifikation dafür zu finden, aber das Netz scheint zuzustimmen, dass es sich um 12 spezielle Fälle handelt (zumindest für HTML 4). Siehe zum Beispiel den folgenden Beitrag: drupal.org/node/1420706#comment-6423420
usemap
Attribut kann nicht mit der Punktnotation festgelegt werden, wenn die Karte dynamisch für ein Bild erstellt wird. Erfordert img.setAttribute('usemap', "#MapName");
Bedeutet Ihre Antwort, dass dies usemap
daher "nicht standardisiert" ist?
Keine der vorherigen Antworten ist vollständig und die meisten enthalten Fehlinformationen.
Es gibt drei Möglichkeiten, auf die Attribute eines DOM- Elements in JavaScript zuzugreifen . Alle drei funktionieren zuverlässig in modernen Browsern, solange Sie wissen, wie man sie verwendet.
element.attributes
Elemente haben eine Eigenschaft Attribute , dass die Renditen ein Live - NamedNodeMap von Attr - Objekten. Die Indizes dieser Sammlung können zwischen den Browsern unterschiedlich sein. Die Bestellung ist also nicht garantiert. NamedNodeMap
Methoden zum Hinzufügen und Entfernen von Attributen ( getNamedItem
und setNamedItem
ist).
Beachten Sie, dass XML zwar explizit zwischen Groß- und Kleinschreibung unterscheidet, die DOM-Spezifikation jedoch die Normalisierung von Zeichenfolgennamen erfordert , sodass bei Namen, an die übergeben wird, getNamedItem
die Groß- und Kleinschreibung nicht berücksichtigt wird.
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
Diese Methoden existieren direkt auf dem Element
ohne Zugriff attributes
und seinen Methoden, führen jedoch dieselben Funktionen aus.
Beachten Sie erneut, dass bei String-Namen die Groß- und Kleinschreibung nicht berücksichtigt wird.
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
Auf viele Attribute kann über praktische Eigenschaften des DOM-Objekts zugegriffen werden. Welche Attribute vorhanden sind, hängt vom Typ des DOM-Knotens ab, nicht davon, welche Attribute im HTML definiert sind. Die Eigenschaften werden irgendwo in der Prototypkette des betreffenden DOM-Objekts definiert. Die definierten spezifischen Eigenschaften hängen vom Typ des Elements ab, auf das Sie zugreifen. Zum Beispiel className
und id
sind Element
auf allen DOM-Knoten definiert und vorhanden, die Elemente sind (dh keine Text- oder Kommentarknoten). Ist value
aber enger. Es ist HTMLInputElement
für andere Elemente definiert und möglicherweise nicht vorhanden.
Beachten Sie, dass bei JavaScript-Eigenschaften zwischen Groß- und Kleinschreibung unterschieden wird. Obwohl die meisten Eigenschaften Kleinbuchstaben verwenden, sind einige camelCase. Überprüfen Sie daher immer die Spezifikation, um sicherzugehen.
Dieses "Diagramm" erfasst einen Teil der Prototypkette für diese DOM-Objekte. Es ist noch nicht einmal fast fertig, aber es erfasst die Gesamtstruktur.
____________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>
Vorsichtsmaßnahme: Dies ist eine Erklärung, wie die HTML-Spezifikation Attribute definiert und moderne Browser damit umgehen. Ich habe nicht versucht, mit den Einschränkungen alter, kaputter Browser umzugehen. Wenn Sie alte Browser unterstützen müssen, müssen Sie zusätzlich zu diesen Informationen wissen, was in diesen Browsern defekt ist.
Ein Fall, bei dem ich festgestellt habe, dass dies setAttribute
erforderlich ist, ist das Ändern von ARIA-Attributen, da keine entsprechenden Eigenschaften vorhanden sind. Beispielsweise
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
Da es so x.arialabel
etwas nicht gibt, müssen Sie setAttribute verwenden.
Edit: x ["aria-label"] funktioniert nicht . Sie brauchen wirklich 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"
Diese Antworten befassen sich nicht wirklich mit der großen Verwirrung zwischen Eigenschaften und Attributen . Abhängig vom Javascript-Prototyp können Sie manchmal die Eigenschaft eines Elements verwenden, um auf Attribute zuzugreifen, und manchmal nicht.
Zunächst müssen Sie sich daran erinnern, dass an HTMLElement
ein Javascript-Objekt ist. Wie alle Objekte haben sie Eigenschaften. Natürlich können Sie eine Eigenschaft erstellen, die fast alles enthält, was Sie möchten HTMLElement
, aber sie muss nichts mit dem DOM zu tun haben (was auf der Seite steht). Die Punktnotation ( .
) steht für Eigenschaften . Jetzt gibt es einige spezielle Eigenschaften , die Attributen zugeordnet sind, und zum Zeitpunkt oder beim Schreiben sind nur 4 garantiert (dazu später mehr).
Alle HTMLElement
s enthalten eine Eigenschaft namens attributes
. HTMLElement.attributes
ist ein Live- NamedNodeMap
Objekt, das sich auf die Elemente im DOM bezieht. "Live" bedeutet, dass sich der Knoten, wenn er sich im DOM ändert, auf der JavaScript-Seite ändert und umgekehrt. DOM-Attribute sind in diesem Fall die fraglichen Knoten. A Node
hat eine .nodeValue
Eigenschaft, die Sie ändern können. NamedNodeMap
Objekte haben eine Funktion namens, setNamedItem
mit der Sie den gesamten Knoten ändern können. Sie können auch direkt über den Schlüssel auf den Knoten zugreifen. Zum Beispiel können Sie sagen, .attributes["dir"]
was dasselbe ist wie .attributes.getNamedItem('dir');
(Randnotiz, NamedNodeMap
bei der die Groß- und Kleinschreibung nicht berücksichtigt wird, sodass Sie auch bestehen können 'DIR'
);
Es gibt eine ähnliche Funktion direkt, in der HTMLElement
Sie einfach aufrufen können, setAttribute
wodurch automatisch ein Knoten erstellt wird, wenn er nicht vorhanden ist, und der festgelegt wird nodeValue
. Es gibt auch einige Attribute, auf die Sie HTMLElement
über spezielle Eigenschaften direkt als Eigenschaften zugreifen können , z dir
. Hier ist eine grobe Abbildung, wie es aussieht:
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 || ''
}
Sie können die dir
Attribute also auf 6 Arten ändern :
// 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';
Sie können alle Eigenschaften mit Methoden # 1-5, aktualisieren , aber nur dir
, id
, lang
, und className
mit Methode # 6.
HTMLElement
hat diese 4 besonderen Eigenschaften. Einige Elemente sind erweiterte Klassen HTMLElement
mit noch mehr zugeordneten Eigenschaften. Zum Beispiel HTMLAnchorElement
hat HTMLAnchorElement.href
, HTMLAnchorElement.rel
und HTMLAnchorElement.target
. Aber Vorsicht , wenn Sie diese Eigenschaften auf Elemente festgelegt , die (wie bei einem nicht die besonderen Eigenschaften haben HTMLTableElement
) , dann die Attribute nicht geändert werden und sie sind einfach, normal benutzerdefinierte Eigenschaften. Zum besseren Verständnis hier ein Beispiel für seine Vererbung:
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 || ''
}
Jetzt die große Warnung: Wie bei allen Javascript-Objekten können Sie benutzerdefinierte Eigenschaften hinzufügen. Diese ändern jedoch nichts am DOM. Du kannst tun:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
Aber das ist das gleiche wie
newElement.myCustomDisplayAttribute = 'block';
Dies bedeutet, dass das Hinzufügen einer benutzerdefinierten Eigenschaft nicht mit verknüpft wird.attributes[attr].nodeValue
.
Performance
Ich habe einen jsperf-Testfall erstellt, um den Unterschied zu zeigen: https://jsperf.com/set-attribute-comparison . Grundsätzlich in der Reihenfolge:
dir
, id
, className
).element.attributes.ATTRIBUTENAME.nodeValue =
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
Schlussfolgerung (TL; DR)
Verwenden Sie die spezielle Eigenschaft Zuordnungen von HTMLElement
: element.dir
, element.id
, element.className
, oder element.lang
.
Wenn Sie zu 100% sicher sind, dass das Element eine Erweiterung HTMLElement
mit einer speziellen Eigenschaft ist, verwenden Sie diese spezielle Zuordnung. (Sie können mit überprüfen if (element instanceof HTMLAnchorElement)
).
Wenn Sie zu 100% sicher sind, dass das Attribut bereits vorhanden ist, verwenden Sie element.attributes.ATTRIBUTENAME.nodeValue = newValue
.
Wenn nicht, verwenden Sie setAttribute()
.
classList
ist zu 100% garantiert, aber es ist keine String-Eigenschaft, sondern ein Live- DOMTokenList
Objekt. Das .className
direkte Einstellen ist schneller als das Manipulieren classList
, aber Sie würden das Ganze überschreiben.
.value
, ändern Sie den internen Wert von HTMLInputElement
, der sich dann in den Attributen widerspiegelt. Sie müssen es auch nicht sein string
. .valueAsNumber
ändert sich value
intern und seine string
Form wird im value
Attribut angezeigt. developer.mozilla.org/en-US/docs/Web/HTML/Attributes
"Wann sollte setAttribute vs .attribute = in JavaScript verwendet werden?"
Eine allgemeine Regel ist, zu verwenden .attribute
und zu überprüfen, ob es im Browser funktioniert.
..Wenn es im Browser funktioniert, können Sie loslegen.
..Wenn dies nicht der Fall ist, verwenden Sie .setAttribute(attribute, value)
statt .attribute
für dieses Attribut.
Spülen-Wiederholen für alle Attribute.
Nun, wenn Sie faul sind, können Sie einfach verwenden .setAttribute
. Das sollte in den meisten Browsern gut funktionieren. (Obwohl Browser, die dies unterstützen, .attribute
es besser optimieren können als .setAttribute(attribute, value)
.)
Dies scheint ein Fall zu sein, in dem es besser ist, setAttribute zu verwenden:
Dev.Opera - Effizientes JavaScript
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);
}
posElem.style = newStyle
nicht in allen Browsern (hat bei mir in Firefox funktioniert)? Wird nur aus Leistungsgründen setAttribute
bevorzugt, um die Neulackierungen zu vermeiden? Ist dann posElem.style.cssText = newStyle
mehr Perfomrant posElem.style = newStyle
?
Methoden zum Festlegen von Attributen (z. B. Klasse) für ein Element: 1. el.className = string 2. el.setAttribute ('class', string) 3. el.attributes.setNamedItem (Objekt) 4. el.setAttributeNode (Knoten)
Ich habe einen einfachen Benchmark-Test gemacht ( hier )
und es scheint, dass setAttributeNode ungefähr dreimal schneller ist als die Verwendung von setAttribute.
Wenn also die Leistung ein Problem darstellt, verwenden Sie "setAttributeNode".
Interessante Entnahme aus dem Google API-Skript zu diesem Thema :
Sie machen es so:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
Beachten Sie, wie sie setAttribute
für "src" und "nonce", dann aber .async = ...
für das Attribut "async" verwendet werden.
Ich bin nicht 100% sicher, aber wahrscheinlich liegt das daran, dass "async" nur in Browsern unterstützt wird, die die direkte .attr =
Zuweisung unterstützen. Es macht also keinen Sinn, es zu versuchen, sestAttribute("async")
denn wenn der Browser es nicht versteht, versteht .async=...
er das Attribut "asynchron" nicht.
Hoffentlich ist dies eine hilfreiche Erkenntnis aus meinem laufenden Forschungsprojekt "Un-minify GAPI" . Korrigiere mich, wenn ich falsch liege.
.setAttribute()
zu wechselte[key] = value
, fing alles an, magisch zu funktionieren.