Anche nell'era dei framework come React e Vue, padroneggiare la manipolazione diretta del DOM rimane una competenza fondamentale. È proprio ciò che i framework gestiscono "sotto il cofano", ed è la chiave per creare componenti web performanti o gestire progetti in Vanilla JavaScript senza dipendenze pesanti. Le API del DOM moderne sono diventate incredibilmente potenti e intuitive: spesso, jQuery è diventato superfluo.
Selezione degli Elementi
// Selezione di un singolo elemento
const header = document.querySelector('.header');
const submitBtn = document.getElementById('submit-btn');
const primoArticolo = document.querySelector('article:first-of-type');
// Selezione multipla (restituisce un NodeList)
const cardList = document.querySelectorAll('.card');
const links = document.querySelectorAll('nav a');
// Iterazione su NodeList
cardList.forEach(card => {
card.classList.add('loaded');
});
// Conversione in Array per utilizzare metodi avanzati (filter, map, ecc.)
const cardArray = [...document.querySelectorAll('.card')];
const cardVisibili = cardArray.filter(c => !c.hidden);
Modifica degli Elementi
const el = document.querySelector('.hero-title');
// Contenuto testuale (sicuro — previene attacchi XSS)
el.textContent = 'Ciao, Mondo!';
// Contenuto HTML (⚠️ Attenzione: rischio XSS con input utente)
el.innerHTML = '<strong>Benvenuto</strong> nel mio sito';
// Gestione Attributi
el.setAttribute('role', 'heading');
el.getAttribute('data-id');
el.removeAttribute('hidden');
// Dataset (gestione attributi data-*)
el.dataset.userId = '123'; // Imposta data-user-id="123"
console.log(el.dataset.userId); // "123"
// Manipolazione Classi
el.classList.add('active', 'visible');
el.classList.remove('loading');
el.classList.toggle('dark-mode');
el.classList.contains('active'); // true/false
el.classList.replace('vecchia-classe', 'nuova-classe');
// Stili inline
el.style.color = '#6366f1';
el.style.setProperty('--accent', '#22d3ee');
Creazione e Inserimento di Elementi
// Crea un nuovo elemento
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<h3>${titolo}</h3>
<p>${descrizione}</p>
`;
// Inserimento strategico
container.appendChild(card); // Alla fine
container.prepend(card); // All'inizio
container.insertBefore(card, riferimento); // Prima di un elemento specifico
// Metodi moderni di inserimento
elemento.before(nuovoElemento); // Prima dell'elemento
elemento.after(nuovoElemento); // Dopo l'elemento
elemento.replaceWith(nuovoElemento); // Sostituzione
// Rimozione
elemento.remove();
// Clonazione di elementi
const clone = template.cloneNode(true); // true = clonazione profonda
Gestione degli Eventi
const button = document.querySelector('#submit');
// Aggiungere un listener
button.addEventListener('click', (event) => {
event.preventDefault();
console.log('Click rilevato!', event.target);
});
// Rimuovere un listener (richiede una funzione nominata)
function gestoreClick(e) { /* ... */ }
button.addEventListener('click', gestoreClick);
button.removeEventListener('click', gestoreClick);
// Eventi comuni
element.addEventListener('input', handler); // Modifiche in tempo reale
element.addEventListener('change', handler); // Cambio valore al termine
element.addEventListener('submit', handler); // Invio form
element.addEventListener('keydown', handler); // Pressione tasti
element.addEventListener('scroll', handler); // Scroll della pagina
Delegazione degli Eventi
Invece di allegare un gestore di eventi a ogni singolo elemento figlio, è molto più efficiente assegnarne uno solo al genitore. Utilizzando event.target e il metodo closest(), puoi identificare con precisione l'elemento interagito, risparmiando memoria e rendendo il codice pronto per elementi creati dinamicamente.
// ❌ Approccio inefficiente — troppi listener
document.querySelectorAll('.card').forEach(card => {
card.addEventListener('click', handleCardClick);
});
// ✅ Approccio professionale — un unico listener sul contenitore
document.querySelector('.card-grid').addEventListener('click', (e) => {
const card = e.target.closest('.card');
if (!card) return; // Se non è una card, ignora
const id = card.dataset.id;
gestisciCard(id);
});
Uso Strategico di <template>
<!-- Template nascosto -->
<template id="card-template">
<div class="card">
<h3 class="card-title"></h3>
<p class="card-desc"></p>
</div>
</template>
<script>
const template = document.getElementById('card-template');
function creaCard(titolo, desc) {
const clone = template.content.cloneNode(true);
clone.querySelector('.card-title').textContent = titolo;
clone.querySelector('.card-desc').textContent = desc;
document.querySelector('.grid').appendChild(clone);
}
</script>
Ottimizzazione delle Performance
- Batching degli aggiornamenti: usa
DocumentFragmentper minimizzare i reflow del browser. - Delegazione sempre: riduci drasticamente il numero di listener in memoria.
- Evita il "Layout Thrashing": separa le operazioni di lettura (es.
offsetHeight) da quelle di scrittura (es.style.top). - Usa
requestAnimationFrame: ideale per animazioni fluide e sincronizzate con il refresh del monitor. - Debounce & Throttle: applica sempre queste tecniche agli eventi rapidi come
scrolloresize.
Prova i nostri Strumenti JavaScript Gratuiti
Ottimizza, minifica e formatta il tuo codice in pochi clic.