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 HTMLElement
jest 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 HTMLElement
s zawierają właściwość o nazwie attributes
. HTMLElement.attributes
to 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 Node
ma .nodeValue
właściwość, którą możesz zmienić. NamedNodeMap
obiekty mają funkcję o nazwie, w setNamedItem
któ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, NamedNodeMap
nie rozróżnia wielkości liter, więc możesz również przekazać 'DIR'
);
Istnieje podobna funkcja bezpośrednio, w HTMLElement
której możesz po prostu wywołać, setAttribute
któ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 HTMLElement
za 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ć dir
atrybuty 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 className
metodą # 6.
Rozszerzenia HTMLElement
HTMLElement
ma te 4 specjalne właściwości. Niektóre elementy są rozszerzonymi klasami o HTMLElement
jeszcze większej liczbie odwzorowanych właściwości. Na przykład, HTMLAnchorElement
ma HTMLAnchorElement.href
, HTMLAnchorElement.rel
i 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 HTMLElement
o 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.