Hledání:getElement*, querySelector*

Vlastnosti navigace DOM jsou skvělé, když jsou prvky blízko sebe. Co když nejsou? Jak získat libovolný prvek stránky?

K tomu existují další metody vyhledávání.

document.getElementById nebo jen id

Pokud má prvek id atribut, můžeme prvek získat pomocí metody document.getElementById(id) , bez ohledu na to, kde to je.

Například:

<div id="elem">
 <div id="elem-content">Element</div>
</div>

<script>
 // get the element
 let elem = document.getElementById('elem');

 // make its background red
 elem.style.background = 'red';
</script>

Existuje také globální proměnná pojmenovaná id který odkazuje na prvek:

<div id="elem">
 <div id="elem-content">Element</div>
</div>

<script>
 // elem is a reference to DOM-element with id="elem"
 elem.style.background = 'red';

 // id="elem-content" has a hyphen inside, so it can't be a variable name
 // ...but we can access it using square brackets: window['elem-content']
</script>

…Pokud nedeklarujeme proměnnou JavaScriptu se stejným názvem, pak má přednost:

<div id="elem"></div>

<script>
 let elem = 5; // now elem is 5, not a reference to <div id="elem">

 alert(elem); // 5
</script>
Pro přístup k prvkům nepoužívejte globální proměnné s názvem id

Toto chování je popsáno ve specifikaci, jde tedy o jakýsi standard. Ale je podporován hlavně kvůli kompatibilitě.

Prohlížeč se nám snaží pomoci smícháním jmenných prostorů JS a DOM. To je v pořádku pro jednoduché skripty vložené do HTML, ale obecně to není dobrá věc. Může docházet ke konfliktům pojmenování. Když člověk čte kód JS a nemá v zobrazení HTML, není zřejmé, odkud proměnná pochází.

Zde v tutoriálu používáme id přímo odkazovat na prvek kvůli stručnosti, když je zřejmé, odkud prvek pochází.

V reálném životě document.getElementById je preferovanou metodou.

id musí být jedinečný

id musí být jedinečný. V dokumentu může být pouze jeden prvek s daným id .

Pokud existuje více prvků se stejným id , pak je chování metod, které jej používají, nepředvídatelné, kupř. document.getElementById může náhodně vrátit kterýkoli z těchto prvků. Držte se prosím pravidla a dodržujte id jedinečný.

Pouze document.getElementById , nikoli anyElem.getElementById

Metoda getElementById lze volat pouze na document objekt. Hledá daný id v celém dokumentu.

querySelectorAll

Zdaleka nejuniverzálnější metoda, elem.querySelectorAll(css) vrátí všechny prvky uvnitř elem odpovídající danému selektoru CSS.

Zde hledáme všechny <li> prvky, které jsou posledními potomky:

<ul>
 <li>The</li>
 <li>test</li>
</ul>
<ul>
 <li>has</li>
 <li>passed</li>
</ul>
<script>
 let elements = document.querySelectorAll('ul > li:last-child');

 for (let elem of elements) {
 alert(elem.innerHTML); // "test", "passed"
 }
</script>

Tato metoda je skutečně výkonná, protože lze použít jakýkoli selektor CSS.

Může také používat pseudotřídy

Pseudotřídy v selektoru CSS jako :hover a :active jsou také podporovány. Například document.querySelectorAll(':hover') vrátí kolekci s prvky, nad kterými je ukazatel nyní (v pořadí vnoření:od nejvzdálenějšího <html> k nejvíce vnořenému).

querySelector

Volání na elem.querySelector(css) vrátí první prvek pro daný selektor CSS.

Jinými slovy, výsledek je stejný jako elem.querySelectorAll(css)[0] , ale druhý hledá všechny prvků a vybrat jeden, zatímco elem.querySelector jen hledá jednu. Psaní je tedy rychlejší a také kratší.

odpovídá

Předchozí metody prohledávaly DOM.

elem.matches(css) nic nehledá, pouze kontroluje, zda elem odpovídá danému CSS-selektoru. Vrací true nebo false .

Tato metoda se hodí, když iterujeme prvky (jako pole nebo tak něco) a snažíme se odfiltrovat ty, které nás zajímají.

Například:

<a href="http://example.com/file.zip">...</a>
<a href="http://ya.ru">...</a>

<script>
 // can be any collection instead of document.body.children
 for (let elem of document.body.children) {
 if (elem.matches('a[href$="zip"]')) {
 alert("The archive reference: " + elem.href );
 }
 }
</script>

nejbližší

Předkové prvku jsou:rodič, rodič rodiče, jeho rodič a tak dále. Předkové společně tvoří řetězec rodičů od živlu až po vrchol.

Metoda elem.closest(css) hledá nejbližšího předka, který odpovídá selektoru CSS. elem sám je také zahrnut do vyhledávání.

Jinými slovy, metoda closest zvedne se od živlu a zkontroluje každého z rodičů. Pokud odpovídá selektoru, hledání se zastaví a vrátí se předchůdce.

Například:

<h1>Contents</h1>

<div class="contents">
 <ul class="book">
 <li class="chapter">Chapter 1</li>
 <li class="chapter">Chapter 2</li>
 </ul>
</div>

<script>
 let chapter = document.querySelector('.chapter'); // LI

 alert(chapter.closest('.book')); // UL
 alert(chapter.closest('.contents')); // DIV

 alert(chapter.closest('h1')); // null (because h1 is not an ancestor)
</script>

getElementsBy*

Existují také další metody, jak hledat uzly podle značky, třídy atd.

Dnes jsou většinou historií, jako querySelector je výkonnější a kratší pro zápis.

Zde je tedy uvádíme hlavně pro úplnost, zatímco stále je můžete najít ve starých skriptech.

  • elem.getElementsByTagName(tag) vyhledá prvky s danou značkou a vrátí jejich kolekci. tag parametr může být také hvězdička "*" pro „libovolné značky“.
  • elem.getElementsByClassName(className) vrátí prvky, které mají danou CSS třídu.
  • document.getElementsByName(name) vrátí prvky s daným name atribut, celý dokument. Velmi zřídka používané.

Například:

// get all divs in the document
let divs = document.getElementsByTagName('div');

Pojďme najít všechny input tagy uvnitř tabulky:

<table id="table">
 <tr>
 <td>Your age:</td>

 <td>
 <label>
 <input type="radio" name="age" value="young" checked> less than 18
 </label>
 <label>
 <input type="radio" name="age" value="mature"> from 18 to 50
 </label>
 <label>
 <input type="radio" name="age" value="senior"> more than 60
 </label>
 </td>
 </tr>
</table>

<script>
 let inputs = table.getElementsByTagName('input');

 for (let input of inputs) {
 alert( input.value + ': ' + input.checked );
 }
</script>
Nezapomeňte na "s" dopis!

Začínající vývojáři někdy zapomínají na písmeno "s" . To znamená, že se snaží zavolat getElementByTagName místo getElementsByTagName .

"s" písmeno v getElementById chybí , protože vrací jeden prvek. Ale getElementsByTagName vrací kolekci prvků, takže je zde "s" uvnitř.

Vrací sbírku, ne prvek!

Další rozšířenou chybou začátečníků je psát:

// doesn't work
document.getElementsByTagName('input').value = 5;

To nebude fungovat, protože to vyžaduje sbírku vstupů a přiřadí hodnotu jemu spíše než prvkům v něm.

Měli bychom buď iterovat kolekci, nebo získat prvek podle jeho indexu a poté přiřadit takto:

// should work (if there's an input)
document.getElementsByTagName('input')[0].value = 5;

Hledám .article prvky:

<form name="my-form">
 <div class="article">Article</div>
 <div class="long article">Long article</div>
</form>

<script>
 // find by name attribute
 let form = document.getElementsByName('my-form')[0];

 // find by class inside the form
 let articles = form.getElementsByClassName('article');
 alert(articles.length); // 2, found two elements with class "article"
</script>

Živé sbírky

Všechny metody "getElementsBy*" vrátit živý sbírka. Takové kolekce vždy odrážejí aktuální stav dokumentu a „automaticky se aktualizují“, když se změní.

V níže uvedeném příkladu jsou dva skripty.

  1. První vytvoří odkaz na kolekci <div> . Nyní je jeho délka 1 .
  2. Druhé skripty se spustí poté, co prohlížeč splňuje ještě jeden <div> , takže jeho délka je 2 .
<div>First div</div>

<script>
 let divs = document.getElementsByTagName('div');
 alert(divs.length); // 1
</script>

<div>Second div</div>

<script>
 alert(divs.length); // 2
</script>

Naproti tomu querySelectorAll vrátí statický sbírka. Je to jako pevné pole prvků.

Pokud jej místo toho použijeme, pak oba skripty vydají 1 :

<div>First div</div>

<script>
 let divs = document.querySelectorAll('div');
 alert(divs.length); // 1
</script>

<div>Second div</div>

<script>
 alert(divs.length); // 1
</script>

Nyní snadno vidíme rozdíl. Po objevení nového div se statická kolekce nezvýšila v dokumentu.

Shrnutí

Existuje 6 hlavních metod hledání uzlů v DOM:

Metoda Vyhledává podle... Lze volat na prvek? Žít?
querySelector Výběr CSS -
querySelectorAll Výběr CSS -
getElementById id - -
getElementsByName name -
getElementsByTagName tag nebo '*'
getElementsByClassName třída

Zdaleka nejpoužívanější jsou querySelector a querySelectorAll , ale getElement(s)By* mohou být sporadicky užitečné nebo je lze nalézt ve starých skriptech.

Kromě toho:

  • Je zde elem.matches(css) zkontrolujte, zda elem odpovídá danému selektoru CSS.
  • Je zde elem.closest(css) hledat nejbližšího předka, který odpovídá danému CSS-selektoru. elem sám je také zkontrolován.

A zmiňme zde ještě jednu metodu, jak ověřit vztah dítě-rodič, protože je někdy užitečná:

  • elemA.contains(elemB) vrátí hodnotu true, pokud elemB je uvnitř elemA (potomek elemA ) nebo když elemA==elemB .