Atributy a vlastnosti

Když prohlížeč načte stránku, „přečte“ (jiné slovo:„analyzuje“) HTML a vygeneruje z něj objekty DOM. U uzlů prvků se většina standardních atributů HTML automaticky stává vlastnostmi objektů DOM.

Pokud je například značka <body id="page"> , pak má objekt DOM body.id="page" .

Ale mapování atributů a vlastností není individuální! V této kapitole se budeme věnovat oddělení těchto dvou pojmů, abychom viděli, jak s nimi pracovat, kdy jsou stejné a kdy se liší.

Vlastnosti modelu DOM

Již jsme viděli vestavěné vlastnosti DOM. Je toho hodně. Technicky nás ale nikdo neomezuje, a pokud jich není dost, můžeme přidat vlastní.

Uzly DOM jsou běžné objekty JavaScriptu. Můžeme je změnit.

Vytvořme například novou vlastnost v document.body :

document.body.myData = {
 name: 'Caesar',
 title: 'Imperator'
};

alert(document.body.myData.title); // Imperator

Můžeme přidat i metodu:

document.body.sayTagName = function() {
 alert(this.tagName);
};

document.body.sayTagName(); // BODY (the value of "this" in the method is document.body)

Můžeme také upravit vestavěné prototypy jako Element.prototype a přidejte nové metody ke všem prvkům:

Element.prototype.sayHi = function() {
 alert(`Hello, I'm ${this.tagName}`);
};

document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY

Vlastnosti a metody DOM se tedy chovají stejně jako u běžných objektů JavaScript:

  • Mohou mít jakoukoli hodnotu.
  • Rozlišují se malá a velká písmena (zapište elem.nodeType , nikoli elem.NoDeTyPe ).

Atributy HTML

V HTML mohou mít značky atributy. Když prohlížeč analyzuje kód HTML, aby vytvořil objekty DOM pro značky, rozpozná standardní atributy a vytváří z nich vlastnosti DOM.

Takže když má prvek id nebo jiný standard atribut, vytvoří se odpovídající vlastnost. To se ale nestane, pokud je atribut nestandardní.

Například:

<body id="test" something="non-standard">
 <script>
 alert(document.body.id); // test
 // non-standard attribute does not yield a property
 alert(document.body.something); // undefined
 </script>
</body>

Upozorňujeme, že standardní atribut pro jeden prvek může být pro jiný neznámý. Například "type" je standardní pro <input> (HTMLInputElement), ale ne pro <body> (HTMLBodyElement). Standardní atributy jsou popsány ve specifikaci pro odpovídající třídu prvků.

Tady to můžeme vidět:

<body id="body" type="...">
 <input id="input" type="text">
 <script>
 alert(input.type); // text
 alert(body.type); // undefined: DOM property not created, because it's non-standard
 </script>
</body>

Pokud je tedy atribut nestandardní, nebude pro něj existovat vlastnost DOM. Existuje způsob, jak získat přístup k těmto atributům?

Tak určitě. Všechny atributy jsou přístupné pomocí následujících metod:

  • elem.hasAttribute(name) – kontroluje existenci.
  • elem.getAttribute(name) – získá hodnotu.
  • elem.setAttribute(name, value) – nastaví hodnotu.
  • elem.removeAttribute(name) – odebere atribut.

Tyto metody fungují přesně s tím, co je napsáno v HTML.

Také je možné číst všechny atributy pomocí elem.attributes :kolekce objektů, které patří do vestavěné třídy Attr s name a value vlastnosti.

Zde je ukázka čtení nestandardní vlastnosti:

<body something="non-standard">
 <script>
 alert(document.body.getAttribute('something')); // non-standard
 </script>
</body>

Atributy HTML mají následující vlastnosti:

  • V jejich názvu se nerozlišují velká a malá písmena (id je stejný jako ID ).
  • Jejich hodnoty jsou vždy řetězce.

Zde je rozšířená ukázka práce s atributy:

<body>
 <div id="elem" about="Elephant"></div>

 <script>
 alert( elem.getAttribute('About') ); // (1) 'Elephant', reading

 elem.setAttribute('Test', 123); // (2), writing

 alert( elem.outerHTML ); // (3), see if the attribute is in HTML (yes)

 for (let attr of elem.attributes) { // (4) list all
 alert( `${attr.name} = ${attr.value}` );
 }
 </script>
</body>

Poznámka:

  1. getAttribute('About') – první písmeno je zde velké a v HTML je to celé malé. Ale na tom nezáleží:názvy atributů nerozlišují malá a velká písmena.
  2. Atributu můžeme přiřadit cokoli, ale stane se z něj řetězec. Takže tady máme "123" jako hodnotu.
  3. Všechny atributy včetně těch, které jsme nastavili, jsou viditelné v outerHTML .
  4. attributes kolekce je iterovatelná a má všechny atributy prvku (standardní i nestandardní) jako objekty s name a value vlastnosti.

Synchronizace atributů vlastností

Když se změní standardní atribut, odpovídající vlastnost se automaticky aktualizuje a (až na některé výjimky) naopak.

V níže uvedeném příkladu id je upraven jako atribut a můžeme vidět změnu vlastnosti. A pak totéž zpětně:

<input>

<script>
 let input = document.querySelector('input');

 // attribute => property
 input.setAttribute('id', 'id');
 alert(input.id); // id (updated)

 // property => attribute
 input.id = 'newId';
 alert(input.getAttribute('id')); // newId (updated)
</script>

Existují však výjimky, například input.value synchronizuje pouze z atributu → do vlastnosti, ale ne zpět:

<input>

<script>
 let input = document.querySelector('input');

 // attribute => property
 input.setAttribute('value', 'text');
 alert(input.value); // text

 // NOT property => attribute
 input.value = 'newValue';
 alert(input.getAttribute('value')); // text (not updated!)
</script>

Ve výše uvedeném příkladu:

  • Změna atributu value aktualizuje vlastnost.
  • Změna vlastnosti však atribut neovlivní.

Tato „funkce“ se může ve skutečnosti hodit, protože akce uživatele mohou vést k value změny a po nich, pokud chceme obnovit „původní“ hodnotu z HTML, je to v atributu.

Vlastnosti DOM jsou zadány

Vlastnosti DOM nejsou vždy řetězce. Například input.checked vlastnost (pro zaškrtávací políčka) je booleovská:

<input id="input" type="checkbox" checked> checkbox

<script>
 alert(input.getAttribute('checked')); // the attribute value is: empty string
 alert(input.checked); // the property value is: true
</script>

Existují další příklady. style atribut je řetězec, ale style vlastnost je objekt:

<div id="div" style="color:red;font-size:120%">Hello</div>

<script>
 // string
 alert(div.getAttribute('style')); // color:red;font-size:120%

 // object
 alert(div.style); // [object CSSStyleDeclaration]
 alert(div.style.color); // red
</script>

Většina vlastností jsou však řetězce.

Poměrně zřídka, i když je typem vlastnosti DOM řetězec, může se lišit od atributu. Například href Vlastnost DOM je vždy úplná URL, i když atribut obsahuje relativní adresu URL nebo jen #hash .

Zde je příklad:

<a id="a" href="#hello">link</a>
<script>
 // attribute
 alert(a.getAttribute('href')); // #hello

 // property
 alert(a.href ); // full URL in the form http://site.com/page#hello
</script>

Pokud potřebujeme hodnotu href nebo jakýkoli jiný atribut přesně tak, jak je napsán v HTML, můžeme použít getAttribute .

Nestandardní atributy, datová sada

Při psaní HTML používáme spoustu standardních atributů. Ale co nestandardní, zakázkové? Nejprve se podívejme, zda jsou užitečné nebo ne? K čemu?

Někdy se k předání vlastních dat z HTML do JavaScriptu nebo k „označení“ prvků HTML pro JavaScript používají nestandardní atributy.

Takhle:

<!-- mark the div to show "name" here -->
<div show-info="name"></div>
<!-- and age here -->
<div show-info="age"></div>

<script>
 // the code finds an element with the mark and shows what's requested
 let user = {
 name: "Pete",
 age: 25
 };

 for(let div of document.querySelectorAll('[show-info]')) {
 // insert the corresponding info into the field
 let field = div.getAttribute('show-info');
 div.innerHTML = user[field]; // first Pete into "name", then 25 into "age"
 }
</script>

Také je lze použít ke stylizaci prvku.

Například zde u objednávky uveďte atribut order-state se používá:

<style>
 /* styles rely on the custom attribute "order-state" */
 .order[order-state="new"] {
 color: green;
 }

 .order[order-state="pending"] {
 color: blue;
 }

 .order[order-state="canceled"] {
 color: red;
 }
</style>

<div class="order" order-state="new">
 A new order.
</div>

<div class="order" order-state="pending">
 A pending order.
</div>

<div class="order" order-state="canceled">
 A canceled order.
</div>

Proč by bylo použití atributu vhodnější než mít třídy jako .order-state-new , .order-state-pending , .order-state-canceled ?

Protože správa atributu je pohodlnější. Stav lze změnit stejně snadno jako:

// a bit simpler than removing old/adding a new class
div.setAttribute('order-state', 'canceled');

Může však nastat problém s vlastními atributy. Co když pro naše účely použijeme nestandardní atribut a později jej standard zavede a přiměje k něčemu? Jazyk HTML je živý, roste a zdá se, že více atributů vyhovuje potřebám vývojářů. V takovém případě může dojít k neočekávaným účinkům.

Aby se předešlo konfliktům, existují atributy data-*.

Všechny atributy začínající na „data-“ jsou vyhrazeny pro použití programátory. Jsou k dispozici v dataset majetek.

Například, pokud elem má atribut s názvem "data-about" , je k dispozici jako elem.dataset.about .

Takhle:

<body data-about="Elephants">
<script>
 alert(document.body.dataset.about); // Elephants
</script>

Víceslovné atributy jako data-order-state mít velbloudí pouzdro:dataset.orderState .

Zde je přepsaný příklad „stavu objednávky“:

<style>
 .order[data-order-state="new"] {
 color: green;
 }

 .order[data-order-state="pending"] {
 color: blue;
 }

 .order[data-order-state="canceled"] {
 color: red;
 }
</style>

<div id="order" class="order" data-order-state="new">
 A new order.
</div>

<script>
 // read
 alert(order.dataset.orderState); // new

 // modify
 order.dataset.orderState = "pending"; // (*)
</script>

Pomocí data-* atributy je platný a bezpečný způsob předávání vlastních dat.

Vezměte prosím na vědomí, že datové atributy můžeme nejen číst, ale také upravovat. Poté CSS odpovídajícím způsobem aktualizuje pohled:v příkladu nad posledním řádkem (*) změní barvu na modrou.

Shrnutí

  • Atributy – je to, co je napsáno v HTML.
  • Vlastnosti – to je to, co je v objektech DOM.

Malé srovnání:

Vlastnosti Atributy
Typ Jakákoli hodnota, standardní vlastnosti mají typy popsané ve specifikaci Řetězec
Jméno V názvu se rozlišují velká a malá písmena V názvu se nerozlišují velká a malá písmena

Metody pro práci s atributy jsou:

  • elem.hasAttribute(name) – zkontrolovat existenci.
  • elem.getAttribute(name) – získat hodnotu.
  • elem.setAttribute(name, value) – pro nastavení hodnoty.
  • elem.removeAttribute(name) – k odstranění atributu.
  • elem.attributes je sbírka všech atributů.

Pro většinu situací je vhodnější použít vlastnosti DOM. Na atributy bychom měli odkazovat pouze tehdy, když nám vlastnosti DOM nevyhovují, když potřebujeme přesně atributy, například:

  • Potřebujeme nestandardní atribut. Ale pokud to začíná data- , pak bychom měli použít dataset .
  • Chceme číst hodnotu „jak je napsáno“ v HTML. Hodnota vlastnosti DOM se může lišit, například href vlastnost je vždy úplná adresa URL a možná budeme chtít získat „původní“ hodnotu.