W3docs

Ricerca in JavaScript: getElement*, querySelector*

Esplora e padroneggia il Document Object Model (DOM) con i metodi getElement* e querySelector* per creare applicazioni web interattive e dinamiche.

Prima di poter modificare, spostare o leggere qualsiasi elemento di una pagina, devi trovare l'elemento desiderato. Questo è il primo passo di quasi ogni operazione sul DOM, e JavaScript mette a disposizione due famiglie di strumenti per farlo:

  • Metodi legacy getElement*getElementById, getElementsByClassName, getElementsByTagName. Sono veloci e restituiscono collezioni live.
  • Metodi moderni querySelector*querySelector, querySelectorAll. Accettano qualsiasi selettore CSS e restituiscono risultati statici.

Questa guida tratta entrambe le famiglie, gli helper matches, closest e contains per verificare e navigare l'albero, e la differenza più importante da non dimenticare: quella tra una collezione live e una statica. Ogni esempio è eseguibile, così puoi vedere il risultato immediatamente.

Una volta trovato un elemento, i passi successivi sono di solito attraversare il DOM per raggiungere gli elementi adiacenti e manipolare il DOM per modificarlo. Per una panoramica più introduttiva, consulta la selezione degli elementi DOM.

Accesso efficiente agli elementi: getElementById

Il metodo getElementById è il modo più rapido e affidabile per accedere a un singolo elemento, poiché un ID deve essere unico all'interno di un documento e i browser indicizzano gli ID internamente. Restituisce l'elemento corrispondente, oppure null se non esiste alcun elemento con quell'ID — quindi controlla sempre che non sia null prima di usare il risultato. Nota che si passa l'ID senza il prefisso # (quello è riservato ai selettori CSS). Nell'esempio seguente, il testo iniziale "Default text" viene sostituito immediatamente.

<!-- snippet: html-result -->

<!DOCTYPE html>
<html>
<head>
    <title>getElementById Example</title>
</head>
<body>
    <div id="main-content">Default text</div>
    <script>
        const element = document.getElementById('main-content');
        element.innerHTML = "Modified text!"
    </script>
</body>
</html>

Accesso a più elementi: getElementsByClassName e getElementsByTagName

Informazione

Quando si selezionano elementi per nome della classe o per nome del tag, si ottiene un HTMLCollection. Questa è una collezione live: si aggiorna automaticamente al variare del DOM. È simile a un array — puoi leggere gli elementi tramite indice (els[0]) e controllare els.length — ma non è un vero array, quindi non dispone di forEach, map o filter. Per iterarla in modo sicuro, convertila prima con Array.from(...) (oppure con lo spread [...els]).

Esempio con getElementsByClassName

Accedi a più elementi con la stessa classe usando getElementsByClassName. In questo esempio abbiamo due elementi div con lo stesso nome di classe. Li modifichiamo entrambi selezionandoli tramite il nome della classe.

<!-- snippet: html-result -->

<!DOCTYPE html>
<html>
<head>
    <title>getElementsByClassName Example</title>
</head>
<body>
    <div class="info">First Info</div>
    <div class="info">Second Info</div>
    <script>
        const infoElements = document.getElementsByClassName('info');
        Array.from(infoElements).forEach(el => el.innerHTML = "MODIFIED!");
    </script>
</body>
</html>

Esempio con getElementsByTagName

Recupera elementi tramite il nome del tag con getElementsByTagName. È del tutto simile all'esempio precedente, ma questa volta selezioniamo in base al nome del tag anziché al nome della classe.

<!-- snippet: html-result -->

<!DOCTYPE html>
<html>
<head>
    <title>getElementsByTagName Example</title>
</head>
<body>
    <p>First Paragraph</p>
    <p>Second Paragraph</p>
    <script>
        const paragraphs = document.getElementsByTagName('p');
        Array.from(paragraphs).forEach(el => el.innerHTML = "MODIFIED!");
    </script>
</body>
</html>

Ricerche flessibili con querySelector e querySelectorAll

Selezione con querySelector

Usa querySelector per trovare il primo elemento che corrisponde a un selettore CSS. In questo esempio selezioniamo il primo elemento con la classe text che è figlio diretto dell'elemento con l'id main.

<!-- snippet: html-result -->

<!DOCTYPE html>
<html>
<head>
    <title>QuerySelector Example</title>
</head>
<body>
    <div id="main"><span class="text">This will be replaced</span></div>
    <div id="other"><span class="text">This one doesn't change</span></div>
    <script>
        const spanInsideDiv = document.querySelector('#main > .text');
        spanInsideDiv.innerHTML = "MODIFIED!";
    </script>
</body>
</html>

Recupero di più elementi con querySelectorAll

querySelectorAll restituisce tutti gli elementi che corrispondono a un selettore CSS, come una NodeList statica. Comodamente, una NodeList ha un forEach integrato, quindi puoi iterarla direttamente senza doverla convertire prima in un array.

La parola statica è importante: querySelectorAll scatta un'istantanea delle corrispondenze nel momento in cui viene chiamato. Se successivamente aggiungi o rimuovi elementi corrispondenti, quella istantanea non cambia. Questo è esattamente l'opposto della HTMLCollection live restituita dai metodi getElementsBy*.

<!-- snippet: html-result -->

<!DOCTYPE html>
<html>
<head>
    <title>QuerySelectorAll Example</title>
</head>
<body>
    <ul>
        <li class="item">Item 1</li>
        <li class="item">Item 2</li>
    </ul>
    <script>
        const items = document.querySelectorAll('.item');
        items.forEach(item => item.innerHTML = "MODIFIED!");
    </script>
</body>
</html>

Live vs. Statico: la trappola delle collezioni

Questa è la trappola in cui cadono i principianti. Una HTMLCollection live riflette lo stato attuale del DOM ad ogni lettura, mentre una NodeList statica è bloccata al momento della selezione. Il frammento di codice seguente mostra entrambe reagire a un elemento aggiunto di recente:

// Suppose the page has two <li class="item"> elements.
const live = document.getElementsByClassName('item');   // live HTMLCollection
const snapshot = document.querySelectorAll('.item');     // static NodeList

console.log(live.length);     // 2
console.log(snapshot.length); // 2

// Now add a third matching element.
const li = document.createElement('li');
li.className = 'item';
document.querySelector('ul').appendChild(li);

console.log(live.length);     // 3  — updated automatically
console.log(snapshot.length); // 2  — still the old snapshot

Perché è importante: iterare su una collezione live mentre si rimuovono elementi corrispondenti è una classica causa di elementi saltati, perché la collezione si riduce durante il ciclo. Una NodeList statica ottenuta da querySelectorAll è più sicura in quel caso, poiché la lista non cambia a metà ciclo.

Verifica e navigazione: matches, closest e contains

La ricerca non consiste solo nel trovare elementi — spesso si ha già un elemento e si deve fare una domanda su di esso.

  • element.matches(selector) restituisce true se l'elemento stesso corrisponde al selettore CSS. Ottimo per la delega degli eventi.
  • element.closest(selector) risale l'albero a partire dall'elemento (includendo l'elemento stesso) e restituisce l'antenato più vicino che corrisponde, oppure null.
  • parent.contains(node) restituisce true se node è il genitore stesso o un suo discendente.

<!-- snippet: html-result -->

<!DOCTYPE html>
<html>
<body>
    <section class="card">
        <button id="save" class="btn primary">Save</button>
    </section>
    <div id="out"></div>
    <script>
        const btn = document.getElementById('save');
        const section = document.querySelector('.card');
        const out = document.getElementById('out');

        out.innerHTML =
            'matches(".primary"): ' + btn.matches('.primary') + '<br>' +
            'closest(".card") is section: ' + (btn.closest('.card') === section) + '<br>' +
            'section.contains(btn): ' + section.contains(btn);
    </script>
</body>
</html>

Quale metodo devo usare?

  • Hai bisogno di un solo elemento tramite ID? Usa getElementById — è il più veloce e chiaro.
  • Hai bisogno di un selettore CSS (discendenti, combinatori, attributi, :not())? Usa querySelector / querySelectorAll.
  • Hai bisogno di una lista live che traccia le modifiche al DOM? Usa getElementsByClassName / getElementsByTagName.
  • Hai un elemento e devi verificare o risalire l'albero? Usa matches, closest o contains.

Conclusione

Trovare gli elementi è la base di ogni script DOM. Usa getElementById per ID singoli, querySelector* per la flessibilità dei selettori CSS, e i metodi getElementsBy* quando hai realmente bisogno di una collezione live — ricordando solo la differenza tra live e statico in modo che le collezioni non ti sorprendano a metà ciclo. Da qui, continua con l'attraversamento del DOM e la manipolazione del DOM.

Esercitati

Pratica
Quali delle seguenti affermazioni su querySelector e getElementById di JavaScript sono corrette?
Quali delle seguenti affermazioni su querySelector e getElementById di JavaScript sono corrette?
Was this page helpful?