Risposte:
Dovresti sempre usare il .attributemodulo diretto (ma vedi il link quirksmode di seguito) se vuoi un accesso programmatico in JavaScript. Dovrebbe gestire correttamente i diversi tipi di attributi (pensa "onload").
Utilizzare getAttribute/ setAttributequando si desidera gestire il DOM così com'è (ad es. Solo testo letterale). Browser diversi confondono i due. Vedi Modalità Quirks: attributo (in) compatibilità .
Da Javascript: la guida definitiva , chiarisce le cose. Nota che gli oggetti HTMLElement di un documento HTML definiscono le proprietà JS che corrispondono a tutti gli attributi HTML standard.
Quindi è necessario utilizzare solo setAttributeper attributi non standard.
Esempio:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
node.frameborderNON è definito, quindi devi ottenereAttribute per recuperare il valore.
frameBorderdiretta, ma nota la maiuscola. Qualcuno ha pensato che fosse una buona idea jolly camelCase gli equivalenti JavaScript degli attributi HTML. Non sono riuscito a trovare alcuna specifica per questo, ma la rete sembra concordare sul fatto che si tratti di 12 casi specifici (almeno per HTML 4). Vedi ad esempio il seguente post: drupal.org/node/1420706#comment-6423420
usemapattributo non può essere impostato usando la notazione punto durante la creazione dinamica della mappa per un'immagine. Richiede img.setAttribute('usemap', "#MapName");La tua risposta implica che usemapè quindi "non standard"?
Nessuna delle risposte precedenti è completa e la maggior parte contiene informazioni errate.
Esistono tre modi per accedere agli attributi di un elemento DOM in JavaScript. Tutti e tre funzionano in modo affidabile nei browser moderni, purché si capisca come utilizzarli.
element.attributesGli elementi hanno attributi di proprietà che restituiscono una NamedNodeMap attiva degli oggetti Attr . Gli indici di questa raccolta potrebbero essere diversi tra i browser. Quindi, l'ordine non è garantito. NamedNodeMapha metodi per aggiungere e rimuovere attributi ( getNamedIteme setNamedItem, rispettivamente).
Si noti che sebbene XML faccia esplicitamente distinzione tra maiuscole e minuscole, la specifica DOM richiede che i nomi delle stringhe vengano normalizzati , quindi i nomi passati non getNamedItemfanno distinzione tra maiuscole e minuscole.
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.setAttributeQuesti metodi esistono direttamente sul Elementsenza la necessità di accedere attributese i suoi metodi ma svolgono le stesse funzioni.
Ancora una volta, nota che il nome della stringa non fa distinzione tra maiuscole e minuscole.
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È possibile accedere a molti attributi utilizzando comode proprietà sull'oggetto DOM. Quali attributi esistono dipendono dal tipo di nodo DOM, non da quali attributi sono definiti nell'HTML. Le proprietà sono definite da qualche parte nella catena di prototipi dell'oggetto DOM in questione. Le proprietà specifiche definite dipenderanno dal tipo di elemento a cui si accede. Ad esempio, classNamee idsono definiti Elemented esistono su tutti i nodi DOM che sono elementi (cioè non nodi di testo o di commento). Ma valueè più stretto. È definito HTMLInputElemente potrebbe non esistere su altri elementi.
Si noti che le proprietà JavaScript fanno distinzione tra maiuscole e minuscole. Anche se la maggior parte delle proprietà utilizzerà lettere minuscole, alcune sono camelCase. Quindi controlla sempre le specifiche per essere sicuro.
Questo "grafico" cattura una parte della catena prototipo per questi oggetti DOM. Non è nemmeno vicino al completamento, ma cattura la struttura generale.
____________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>
Avvertenza: questa è una spiegazione di come definiscono le specifiche HTML e i browser moderni gestiscono gli attributi. Non ho tentato di affrontare i limiti dei browser antichi e rotti. Se è necessario supportare i browser precedenti, oltre a queste informazioni, è necessario sapere cosa non funziona in tali browser.
Un caso che ho trovato dove setAttributeè necessario è quando si cambiano gli attributi ARIA, poiché non ci sono proprietà corrispondenti. Per esempio
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
Non c'è x.arialabelniente del genere, quindi devi usare setAttribute.
Modifica: x ["aria-label"] non funziona . Hai davvero bisogno di 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"
Queste risposte non affrontano realmente la grande confusione tra proprietà e attributi . Inoltre, a seconda del prototipo Javascript, a volte è possibile utilizzare la proprietà di un elemento per accedere a un attributo, a volte no.
Innanzitutto, devi ricordare che an HTMLElementè un oggetto Javascript. Come tutti gli oggetti, hanno proprietà. Certo, puoi creare una proprietà chiamata quasi tutto quello che vuoi all'interno HTMLElement, ma non deve fare nulla con il DOM (cosa c'è nella pagina). La notazione punto ( .) è per le proprietà . Ora, ci sono alcune proprietà speciali che sono mappate agli attributi, e al momento o in scrittura ce ne sono solo 4 che sono garantite (ne parleremo più avanti).
Tutti HTMLElementincludono una proprietà chiamata attributes. HTMLElement.attributesè un oggetto live NamedNodeMap che si riferisce agli elementi nel DOM. "In diretta" significa che quando il nodo cambia nel DOM, cambiano sul lato JavaScript e viceversa. Gli attributi DOM, in questo caso, sono i nodi in questione. A Nodeha una .nodeValueproprietà che puoi modificare. NamedNodeMapgli oggetti hanno una funzione chiamata in setNamedItemcui è possibile cambiare l'intero nodo. È inoltre possibile accedere direttamente al nodo tramite la chiave. Ad esempio, puoi dire .attributes["dir"]quale è lo stesso di .attributes.getNamedItem('dir');(Nota a margine, non NamedNodeMapfa distinzione tra maiuscole e minuscole, quindi puoi anche passare 'DIR');
C'è una funzione simile direttamente in HTMLElementcui puoi semplicemente chiamare setAttributeche creerà automaticamente un nodo se non esiste e imposta il nodeValue. Ci sono anche alcuni attributi a cui puoi accedere direttamente come proprietà HTMLElementtramite proprietà speciali , come dir. Ecco una mappatura approssimativa di come appare:
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 || ''
}
Quindi puoi modificare gli dirattributi in 6 modi:
// 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';
È possibile aggiornare tutte le proprietà con i metodi # 1-5, ma solo dir, id, lang, e classNamecon il metodo # 6.
HTMLElementha quelle 4 proprietà speciali. Alcuni elementi sono classi estese di HTMLElementproprietà ancora più mappate. Ad esempio, HTMLAnchorElementha HTMLAnchorElement.href, HTMLAnchorElement.rele HTMLAnchorElement.target. Ma attenzione , se si impostano quelle proprietà su elementi che non hanno quelle proprietà speciali (come su a HTMLTableElement), gli attributi non vengono modificati e sono solo normali proprietà personalizzate. Per capire meglio, ecco un esempio della sua eredità:
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 || ''
}
Ora il grande avvertimento: come tutti gli oggetti Javascript , è possibile aggiungere proprietà personalizzate. Ma quelli non cambieranno nulla sul DOM. Tu puoi fare:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
Ma è lo stesso di
newElement.myCustomDisplayAttribute = 'block';
Ciò significa che l'aggiunta di una proprietà personalizzata non verrà collegata.attributes[attr].nodeValue .
Prestazione
Ho creato un caso di test jsperf per mostrare la differenza: https://jsperf.com/set-attribute-comparison . Fondamentalmente, per:
dir, id, className).element.attributes.ATTRIBUTENAME.nodeValue = element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValueelement.attributes.ATTRIBUTENAME = newNode element.attributes.setNamedItem(ATTRIBUTENAME) = newNodeConclusione (TL; DR)
Utilizzare i mapping delle proprietà speciali da HTMLElement: element.dir, element.id, element.className, o element.lang.
Se sei sicuro al 100% che l'elemento sia esteso HTMLElementcon una proprietà speciale, usa quel mapping speciale. (Puoi verificare con if (element instanceof HTMLAnchorElement)).
Se sei sicuro al 100% che l'attributo esiste già, usa element.attributes.ATTRIBUTENAME.nodeValue = newValue.
In caso contrario, utilizzare setAttribute().
classListè garantito al 100%, ma non è una proprietà stringa, è un DOMTokenListoggetto live . L'impostazione .classNamediretta è più veloce della manipolazione classList, ma sovrascriveresti l'intera cosa.
.value, stai cambiando il valore interno di HTMLInputElement, che si riflette poi sugli attributi. Inoltre non devono essere string. .valueAsNumbercambierà value internamente e la sua stringforma apparirà valuenell'attributo. developer.mozilla.org/en-US/docs/Web/HTML/Attributes
"Quando utilizzare setAttribute vs .attribute = in JavaScript?"
Una regola generale è quella di utilizzare .attributee verificare se funziona sul browser.
..Se funziona sul browser, sei a posto.
..Se non è così, usa .setAttribute(attribute, value)invece .attributeper quel attributo.
Risciacqua-ripeti per tutti gli attributi.
Bene, se sei pigro puoi semplicemente usare .setAttribute. Questo dovrebbe funzionare bene sulla maggior parte dei browser. (Anche se i browser che supportano .attributepossono ottimizzarlo meglio di .setAttribute(attribute, value).)
Questo sembra un caso in cui è meglio usare setAttribute:
Dev.Opera - JavaScript efficiente
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 = newStylefunziona in tutti i browser (ha funzionato per me in Firefox)? È solo per motivi prestazionali che setAttributesi preferisce, evitando le trattenute? posElem.style.cssText = newStyleAllora è più perfetto posElem.style = newStyle?
metodi per impostare gli attributi (ad esempio la classe) su un elemento: 1. el.className = string 2. el.setAttribute ('class', string) 3. el.attributes.setNamedItem (oggetto) 4. el.setAttributeNode (nodo)
Ho fatto un semplice test di riferimento ( qui )
e sembra che setAttributeNode sia circa 3 volte più veloce rispetto all'uso di setAttribute.
quindi se le prestazioni sono un problema - usa "setAttributeNode"
Interessante asporto dallo script dell'API di Google in merito a questo:
Lo fanno così:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
Notate come usano setAttributeper "src" e "nonce", ma poi .async = ...per l'attributo "asincrono".
Non sono sicuro al 100%, ma probabilmente è perché "asincrono" è supportato solo su browser che supportano l' .attr =assegnazione diretta . Quindi, non ha senso provare sestAttribute("async")perché se il browser non capisce .async=..., non capirà l'attributo "asincrono".
Spero che sia una visione utile del mio progetto di ricerca "Un-minify GAPI" in corso . Correggimi se sbaglio.
.setAttribute()a[key] = value, tutto ha iniziato a funzionare magicamente.