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

Selettori di Nuova Generazione
// 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

Contenuto, Attributi e Classi CSS
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

Creazione Dinamica nel DOM
// 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

addEventListener in dettaglio
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.

Pattern di Delegazione Eventi
// ❌ 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>

Modelli HTML riutilizzabili
<!-- 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 DocumentFragment per 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 scroll o resize.

Prova i nostri Strumenti JavaScript Gratuiti

Ottimizza, minifica e formatta il tuo codice in pochi clic.