Te odpowiedzi nie są odpowiedzią na duże zamieszanie między właściwościami a atrybutami . Ponadto, w zależności od prototypu Javascript, czasami można użyć właściwości elementu, aby uzyskać dostęp do atrybutów, a czasem nie.
Najpierw musisz pamiętać, że an HTMLElementjest obiektem Javascript. Podobnie jak wszystkie obiekty mają właściwości. Jasne, możesz utworzyć właściwość o nazwie prawie wszystko, co chcesz w środku HTMLElement, ale nie musi ona nic robić z DOM (co jest na stronie). Notacja kropkowa ( .) dotyczy właściwości . Teraz istnieją pewne specjalne właściwości, które są mapowane na atrybuty, a w tym czasie lub podczas pisania są tylko 4, które są gwarantowane (więcej na ten temat później).
Wszystkie HTMLElements zawierają właściwość o nazwie attributes. HTMLElement.attributesto obiekt na żywo, NamedNodeMap który odnosi się do elementów w DOM. „Na żywo” oznacza, że gdy węzeł zmienia się w DOM, zmieniają się po stronie JavaScript i odwrotnie. W tym przypadku atrybutami DOM są omawiane węzły. A Nodema .nodeValuewłaściwość, którą możesz zmienić. NamedNodeMapobiekty mają funkcję o nazwie, w setNamedItemktórej można zmienić cały węzeł. Możesz także uzyskać bezpośredni dostęp do węzła za pomocą klucza. Na przykład możesz powiedzieć, .attributes["dir"]który jest taki sam jak .attributes.getNamedItem('dir');(Uwaga boczna, NamedNodeMapnie rozróżnia wielkości liter, więc możesz również przekazać 'DIR');
Istnieje podobna funkcja bezpośrednio, w HTMLElementktórej możesz po prostu wywołać, setAttributektóra automatycznie utworzy węzeł, jeśli nie istnieje i ustawi nodeValue. Istnieją również niektóre atrybuty, do których można uzyskać bezpośredni dostęp jako właściwości HTMLElementza pośrednictwem specjalnych właściwości , takich jak dir. Oto przybliżone odwzorowanie tego, jak to wygląda:
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 || ''
}
Możesz więc zmienić diratrybuty na 6 sposobów:
// 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';
Można zaktualizować wszystkie właściwości z metodami # 1-5, ale tylko dir, id, lang, i classNamemetodą # 6.
Rozszerzenia HTMLElement
HTMLElementma te 4 specjalne właściwości. Niektóre elementy są rozszerzonymi klasami o HTMLElementjeszcze większej liczbie odwzorowanych właściwości. Na przykład, HTMLAnchorElementma HTMLAnchorElement.href, HTMLAnchorElement.reli HTMLAnchorElement.target. Ale uwaga : jeśli ustawisz te właściwości na elementach, które nie mają tych specjalnych właściwości (jak na a HTMLTableElement), wówczas atrybuty nie zostaną zmienione i będą to zwykłe niestandardowe właściwości. Aby lepiej zrozumieć, oto przykład jego dziedziczenia:
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 || ''
}
Właściwości niestandardowe
Teraz wielkie ostrzeżenie: Jak wszystkie obiekty JavaScript , możesz dodawać własne właściwości. Ale to nic nie zmieni w DOM. Możesz to zrobić:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
Ale to to samo co
newElement.myCustomDisplayAttribute = 'block';
Oznacza to, że dodanie niestandardowej właściwości nie zostanie połączone.attributes[attr].nodeValue .
Występ
Zbudowałem skrzynkę testową jsperf, aby pokazać różnicę: https://jsperf.com/set-attribute-comparison . Zasadniczo w celu:
- Właściwości niestandardowe, ponieważ nie wpływają na DOM i nie są atrybutami .
- Specjalne mapowania świadczone przez przeglądarkę (
dir, id, className).
- Jeśli atrybuty już istnieją ,
element.attributes.ATTRIBUTENAME.nodeValue =
- setAttribute ();
- Jeśli atrybuty już istnieją ,
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
Wniosek (TL; DR)
Za pomocą specjalnych mapowania własności z HTMLElement: element.dir, element.id, element.className, lub element.lang.
Jeśli masz 100% pewności, że element jest rozszerzeniem HTMLElemento specjalnej właściwości, użyj tego specjalnego odwzorowania. (Możesz to sprawdzić za pomocą if (element instanceof HTMLAnchorElement)).
Jeśli masz 100% pewności, że atrybut już istnieje, użyj element.attributes.ATTRIBUTENAME.nodeValue = newValue.
Jeśli nie, użyj setAttribute().
.setAttribute()celu[key] = value, wszystko zaczęło się w magiczny sposób działa.