Nodi del DOM in JavaScript
Il DOM è un concetto fondamentale nello sviluppo web: scopri i tipi di nodi, come identificarli e come crearli, aggiungerli, rimuoverli e sostituirli.
Comprendere i Nodi del DOM
Il Document Object Model (DOM) è un concetto fondamentale nello sviluppo web, che funge da interfaccia tra i documenti HTML e JavaScript. Quando una pagina web si carica, il browser analizza l'HTML e costruisce il DOM — un albero di oggetti in memoria, sempre aggiornato, che JavaScript può leggere e modificare. Ogni modifica apportata al DOM si riflette immediatamente sulla pagina, ed è proprio questo che rende possibili le applicazioni web interattive.
Questa guida tratta i nodi del DOM: cosa sono, i diversi tipi che si incontrano, come identificarli e come crearli, aggiungerli, rimuoverli e sostituirli. Al termine comprenderai i mattoni su cui si basa ogni tecnica DOM di livello superiore — come la selezione degli elementi o la navigazione dell'albero.
Cos'è un Nodo del DOM?
Un nodo è l'unità più basilare dell'albero del DOM. Tutto ciò che si trova in un documento — elementi, il testo al loro interno, attributi e persino i commenti — è rappresentato come un nodo. Ogni nodo è un object che eredita dalla classe integrata Node, quindi condividono tutti un insieme comune di proprietà (nodeType, nodeName, parentNode, childNodes, e così via) usate per la navigazione e la manipolazione.
Un modo utile per visualizzarlo: l'HTML che scrivi è la ricetta, e il DOM è l'object live che il browser prepara da quella ricetta. Una volta caricata la pagina, non si modifica più il testo HTML — si modificano i nodi.
<!DOCTYPE html>
<html>
<head>
<title>DOM Nodes Example</title>
</head>
<body>
<div id="example">
<!-- This is a comment node -->
<p>This is a text node within an element node.</p>
</div>
<script>
let exampleDiv = document.getElementById('example');
exampleDiv.style.border = '2px solid blue'; // Highlight the div element
exampleDiv.style.padding = '10px';
</script>
</body>
</html>Spiegazione: In questo esempio, accediamo al div con ID example e applichiamo stili CSS per distinguerlo visivamente. Questo dimostra come manipolare direttamente le proprietà di stile di un nodo elemento, rendendolo più evidente sulla pagina.
I Diversi Tipi di Nodi del DOM
Ogni nodo ha una proprietà numerica nodeType che indica di che tipo di nodo si tratta. I tipi più comuni con cui lavorerai sono:
nodeType | Costante | Significato |
|---|---|---|
1 | Node.ELEMENT_NODE | Un elemento HTML come <div> o <p> |
3 | Node.TEXT_NODE | Il testo all'interno di un elemento (inclusi gli spazi bianchi) |
8 | Node.COMMENT_NODE | Un commento HTML (<!-- ... -->) |
9 | Node.DOCUMENT_NODE | L'object document stesso, la radice dell'albero |
Una sorpresa comune per i principianti: gli spazi bianchi contano come nodi di testo. Le interruzioni di riga e i rientri tra i tag creano nodi di testo vuoti, motivo per cui childNodes restituisce spesso più elementi del previsto. (Se vuoi solo i figli elemento e vuoi saltare quei nodi di testo con spazi bianchi, usa children invece di childNodes.) Anche gli attributi sono nodi, ma il codice moderno li legge con getAttribute() / setAttribute() piuttosto che navigare direttamente i nodi attributo.
L'esempio seguente scorre i nodi figli di un <div> e riporta il tipo di ciascuno:
<!DOCTYPE html>
<html>
<head>
<title>Node Types Interactive Example</title>
<style>
#info {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
#output {
border: 1px solid #ccc;
padding: 10px;
}
button {
cursor: pointer;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="info">
<!-- This is a comment node -->
<p>Element node with a <span>child element node</span> and some text.</p>
</div>
<button onclick="displayNodeTypes()">Show Node Types</button>
<div id="output">Node types will be displayed here.</div>
<script>
function displayNodeTypes() {
const infoDiv = document.getElementById('info');
const outputDiv = document.getElementById('output');
outputDiv.innerHTML = ''; // Clear previous output
const nodeTypes = [];
// Iterate over all child nodes of the div
infoDiv.childNodes.forEach(node => {
let typeDescription = '';
switch(node.nodeType) {
case Node.ELEMENT_NODE:
typeDescription = 'Element node: ' + node.tagName;
break;
case Node.TEXT_NODE:
// Trim text content and check if it's not empty
let textContent = node.textContent.trim();
if (textContent) {
typeDescription = 'Text node: "' + textContent + '"';
}
break;
case Node.COMMENT_NODE:
typeDescription = 'Comment node: "' + node.textContent.trim() + '"';
break;
}
// Only add non-empty descriptions
if (typeDescription) {
nodeTypes.push(typeDescription);
const p = document.createElement('p');
p.textContent = typeDescription;
outputDiv.appendChild(p);
}
});
// If no nodes are visible or found
if (nodeTypes.length === 0) {
outputDiv.textContent = 'No visible nodes found.';
}
}
</script>
</body>
</html>Il documento HTML mostra come identificare e visualizzare diversi tipi di nodi del DOM (come nodi elemento, testo e commento). Include una sezione con stile per mostrare questi nodi, un pulsante che attiva una funzione JavaScript per analizzare e elencare questi nodi, e un'area per visualizzare i risultati. La funzione JavaScript ispeziona ogni nodo all'interno di una parte designata del documento, lo categorizza e ne visualizza il tipo e i dettagli.
Manipolazione dei Nodi del DOM
Le pagine interattive vengono costruite modificando i nodi dopo che la pagina è stata caricata. Le quattro operazioni più utilizzate sono creare, aggiungere, rimuovere e sostituire nodi. Per una panoramica più ampia delle tecniche costruite su queste basi, consulta la manipolazione del DOM.
Creare e Aggiungere Nodi
Creare un nodo e aggiungerlo sono due passaggi separati. document.createElement() crea un nodo scollegato che non è ancora nella pagina; appendChild() (o append(), prepend(), insertBefore()) è ciò che lo inserisce effettivamente nell'albero:
<!DOCTYPE html>
<html>
<head>
<title>Add Node Example</title>
</head>
<body>
<button onclick="addNewParagraph()">Add Paragraph</button>
<script>
function addNewParagraph() {
let newNode = document.createElement('p');
newNode.textContent = 'This is a new paragraph.';
document.body.appendChild(newNode);
}
</script>
</body>
</html>Spiegazione: Questo esempio include un pulsante che, quando viene cliccato, attiva una funzione per creare un nuovo elemento paragrafo (<p>) e lo aggiunge al corpo del documento. Dimostra come JavaScript possa essere utilizzato per aggiungere contenuto dinamicamente a una pagina, il che è particolarmente utile per le applicazioni che devono aggiornarsi in tempo reale senza ricaricare la pagina.
Rimuovere Nodi
Per rimuovere un nodo dalla pagina, chiama removeChild() sul suo genitore, oppure — più semplicemente nei browser moderni — chiama node.remove() direttamente sul nodo stesso. L'esempio usa removeChild() in modo da poter vedere esplicitamente la relazione genitore/figlio:
<!DOCTYPE html>
<html>
<head>
<title>Remove Node Example</title>
</head>
<body>
<div id="container">
<p id="toBeRemoved">This paragraph will be removed. <button onclick="removeParagraph()">Remove</button></p>
</div>
<script>
function removeParagraph() {
let parentNode = document.getElementById('container');
let childNode = document.getElementById('toBeRemoved');
parentNode.removeChild(childNode);
}
</script>
</body>
</html>Spiegazione: Questo script fornisce una dimostrazione pratica della rimozione di un elemento DOM tramite un pulsante incorporato nel paragrafo stesso. Il metodo removeChild() viene usato per rimuovere l'elemento specificato, mostrando un'azione dinamica avviata dall'utente che altera direttamente la struttura del documento.
Sostituire Nodi
replaceChild(newNode, oldNode) scambia un nodo con un altro in un unico passaggio, preservando la posizione del vecchio nodo nell'albero:
<!DOCTYPE html>
<html>
<head>
<title>Replace Node Example</title>
</head>
<body>
<div id="oldElement">This element will be replaced. <button onclick="replaceElement()">Replace</button></div>
<script>
function replaceElement() {
let newNode = document.createElement('div');
newNode.textContent = 'This is a replacement.';
let oldNode = document.getElementById('oldElement');
oldNode.parentNode.replaceChild(newNode, oldNode);
}
</script>
</body>
</html>Spiegazione: In questo esempio interattivo, un pulsante attiva la sostituzione di un div esistente con un div appena creato. Questo illustra il metodo replaceChild(), particolarmente utile nelle situazioni in cui un elemento deve essere aggiornato in base alle azioni dell'utente o a eventi esterni, come la ricezione di nuovi dati da un server.
Best Practice e Consigli
- Minimizza le manipolazioni del DOM: Ogni modifica può indurre il browser a ricalcolare il layout (reflow) e a ridisegnare la pagina (repaint). Raggruppa le modifiche invece di toccare il DOM in un ciclo stretto.
- Prima leggi, poi scrivi: Mescolare letture (come
offsetHeight) e scritture all'interno di un ciclo forza ripetuti layout thrashing. Raggruppa tutte le letture insieme e tutte le scritture insieme. - Costruisci fuori schermo, inserisci una sola volta: Usa un
DocumentFragment(mostrato di seguito) per assemblare molti elementi prima di inserirli in un'unica operazione. - Memorizza nella cache le selezioni: Conserva i risultati di
getElementById/querySelectorin una variabile invece di interrogare ripetutamente lo stesso elemento. Vedi ottimizzazione delle prestazioni del DOM per ulteriori informazioni.
Assicurati sempre la compatibilità cross-browser quando esegui manipolazioni del DOM. Testare su browser diversi aiuta a prevenire comportamenti imprevisti e garantisce un'esperienza utente coerente.
Esempio con DocumentFragment
Un DocumentFragment è un contenitore leggero e fuori schermo per i nodi. Poiché non fa parte del documento live, aggiungere nodi a esso non ha alcun costo in termini di layout — il browser esegue il reflow solo una volta, quando inserisci l'intero frammento nella pagina. Questo lo rende ideale per aggiungere molti elementi contemporaneamente:
<!DOCTYPE html>
<html>
<head>
<title>DocumentFragment Example</title>
</head>
<body>
<div id="list-container">
<h2>Item List</h2>
<ul id="item-list">
<!-- Items will be added here -->
</ul>
<button id="add-items">Add 100 Items</button>
</div>
<script>
const itemList = document.getElementById('item-list');
const addItemsButton = document.getElementById('add-items');
addItemsButton.addEventListener('click', () => {
// Create a DocumentFragment
const fragment = document.createDocumentFragment();
// Add 100 list items to the fragment
for (let i = 1; i <= 100; i++) {
const listItem = document.createElement('li');
listItem.textContent = `Item ${i}`;
fragment.appendChild(listItem);
}
// Append the fragment to the item list
itemList.appendChild(fragment);
});
</script>
</body>
</html>- Iniziamo selezionando l'elemento
<ul>dove verranno aggiunti i nuovi elementi e il pulsante che ne attiverà l'aggiunta. - Quando viene cliccato il pulsante "Add 100 Items", creiamo un object
DocumentFragment. - Poi creiamo 100 elementi
<li>in un ciclo, impostiamo il loro contenuto testuale e aggiungiamo ciascuno alDocumentFragment. - Infine, aggiungiamo il
DocumentFragmentall'elemento<ul>. Poiché il frammento non fa parte del DOM live durante la fase di costruzione, questo approccio minimizza i reflow e i repaint, migliorando le prestazioni.
Usare DocumentFragment è particolarmente utile quando è necessario aggiungere un gran numero di elementi al DOM contemporaneamente, poiché riduce il sovraccarico associato a più reflow e repaint, portando ad aggiornamenti più fluidi e veloci.
Nodi del DOM vs Alberi del DOM
I nodi del DOM e gli alberi del DOM sono concetti correlati, ma si riferiscono a diversi aspetti di come un documento web è strutturato e manipolato:
- Nodi del DOM: Un nodo del DOM è un componente individuale all'interno del Document Object Model (DOM). Ogni elemento, testo, commento e attributo in un documento HTML o XML è considerato un nodo. I nodi sono i mattoni fondamentali di un documento. Ad esempio, un tag
<h1>, il testo all'interno di quel tag, e persino gli attributi di quel tag (comeclass="title") sono tutti nodi separati. - Albero del DOM: L'albero del DOM si riferisce all'intera struttura o gerarchia dei nodi così come sono organizzati nel documento. È una rappresentazione ad albero che mostra come tutti i nodi in un documento siano correlati tra loro. I nodi in questo albero hanno relazioni genitore-figlio, proprio come cartelle e file sul computer. Ad esempio, in un documento HTML, il nodo
<body>potrebbe essere un nodo genitore, con diversi nodi figli come<div>,<p>e<img>che rappresentano diverse parti della pagina web.
In termini semplici, puoi pensare a un nodo del DOM come a un singolo punto o a un pezzo di un puzzle più grande, mentre l'albero del DOM rappresenta il puzzle completo o l'intero insieme di relazioni tra questi punti. L'albero del DOM è utile per navigare e manipolare la struttura di un documento tramite linguaggi di programmazione come JavaScript, poiché consente agli sviluppatori di trovare (selezionare), modificare o aggiornare gli elementi in modo efficiente all'interno della gerarchia annidata.
Conclusione
I nodi sono gli atomi del DOM. Una volta che sai riconoscere i diversi tipi di nodi, leggere il nodeType di un nodo e creare, aggiungere, rimuovere e sostituire nodi con sicurezza, ogni compito DOM di livello superiore diventa affrontabile. Tieni a mente le prestazioni — raggruppa le modifiche e ricorri a un DocumentFragment quando inserisci molti elementi contemporaneamente.
Cosa leggere dopo
- Proprietà dei nodi: tipo, tag e contenuti — approfondisci
nodeType,nodeName,textContente altro. - Selezione degli elementi del DOM — trova i nodi con cui vuoi lavorare.
- Navigazione del DOM — spostati tra nodi genitore, figlio e fratello.
- Manipolazione del DOM — un toolkit più completo costruito sulle operazioni trattate qui.