Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 76 di 112
  • livello avanzato
Indice lezioni

Mutation observer e mutation event

Creare UI che reagiscono in real time a qualunque evento del DOM rilevato sul browser o sul device, come il caricamento della pagina o di particolari asset
Creare UI che reagiscono in real time a qualunque evento del DOM rilevato sul browser o sul device, come il caricamento della pagina o di particolari asset
Link copiato negli appunti

Gli eventi del DOM ci consentono di scrivere codice che reagisce all'interazione con le pagine HTML. Abbiamo visto come alcuni eventi non sono generati direttamente dall'utente ma sono una conseguenza di altri eventi. Un tipico esempio è il caricamento di una nuova pagina che segnala il fatto che il browser ha completato la generazione della struttura del DOM.

Nello sviluppo di un'applicazione può essere interessante effettuare elaborazioni o personalizzazioni in base alle variazioni della struttura del DOM. Potremmo ad esempio voler sapere se è stato aggiunto o eliminato un elemento o un suo attributo o se ne è stato modificato il contenuto.

Mutation Observer

La soluzione proposta dal W3C è quella dei Mutation observer.

A differenza dei Mutation event (di cui parliamo tra breve), gli observer non sono eventi, ma degli oggetti che monitorano elementi del DOM ed eseguono una funzione di callback in corrispondenza di una o più modifiche della loro struttura o dei contenuti. Con questo approccio la gestione delle variazioni del DOM non è sincrona e le variazioni vengono riportate in blocco al gestore JavaScript e non man mano che si verificano, evitando quindi un ingolfamento della coda degli eventi ed una paralisi del browser.

Esaminiamo in concreto come utilizzare i Mutation observer. Nelle sue linee essenziali, per gestire le variazioni degli elementi del DOM dobbiamo innanzitutto creare un Mutation observer ed assegnargli la funzione di callback da eseguire:

// mutationManager è una funzione di callback
// che utilizzeremo per sfruttare i dati acquisiti
// dall'observer
var mutationManager = function(mutationRecords) {
	// ...
};
var observer = new MutationObserver(mutationManager);

Nella signature della funzione di callback dovrà necessariamente esserci come argomento un array di oggetti MutationRecords che servirà a contenere le informazioni sulle variazioni avvenute all'elemento in osservazione. Prima di analizzare in dettaglio come interpretare queste informazioni, vediamo come indicare al Mutation observer l'elemento da monitorare (target) e a quali variazioni siamo interessati.

var div = document.getElementById("myDiv");  
observer.observe(div, { childList: true, attributes: true });

Il tutto viene effettuato tramite il metodo observe() che prevede due parametri:

  • il primo è il target: l'elemento da tenere sotto osservazione;
  • il secondo è un oggetto che descrive le variazioni a cui siamo interessati.

Nell'esempio abbiamo indicato di voler osservare le variazioni degli attributi del div myDiv e di eventuali modifiche dei suoi figli. Le possibili variazioni del DOM che possiamo osservare sono riassunte dalle seguenti proprietà:

Proprietà Descrizione
attributes Valore booleano per l'osservazionedi variazioni degli attributi dell'elemento
attributeOldValue Valore booleano che consente diinserire nei Mutation record il vecchio valore di unattributo (solo se attributes è true)
characterData Valore booleano per l'osservazionedi variazioni del contenuto dell'elemento
characterDataOldValue Valore booleano che consente diinserire nei Mutation record il vecchio valore delcontenuto dell'elemento (solo se characterData ètrue)
childList Valore booleano che consentel'osservazione di variazioni dei figli dell'elemento
subtree Valore booleano che prevedel'osservazione di variazioni di tutti i discendenti dell'elemento
attributeFilter Array di nomi di attributi da teneresotto osservazione (es.: ["class", "src"])

Una volta impostato il Mutation observer, la nostra funzione di callback verrà invocata quando verranno rilevate le variazioni a cui siamo interessati. Come accennato prima, la funzione riceverà un array di Mutation record con i dettagli sulle variazioni avvenute.

NOTA: È importante comprendere che la funzione di callback non sarà invocata dall'observer nel momento in cui si verifica la variazione di un elemento, ma al termine dell'esecuzione della funzione o comunque del blocco di codice che modifica il DOM. Questo fa in modo che possano verificarsi più variazioni al DOM, ciascuna delle quali viene rappresentata da un singolo Mutation record.

Il mutation record

Un Mutation record è un oggetto che prevede le seguenti proprietà:

Proprietà Descrizione
type Il tipo di variazione rilevata. Ipossibili valori sono attribute, characterData ochildList
target L'elemento su cui è statarilevata la variazione
addedNodes Un array di nodi aggiunti al DOM
removedNodes Un array di nodi rimossi dal DOM
nextSibling L'eventuale elemento successivoall'elemento che è stato aggiunto o rimosso
previousSibling L'eventuale elemento precedenteall'elemento che è stato aggiunto o rimosso
attributeName Il nome dell'attributo modificato
oldValue Il valore dell'attributo o delcontenuto precedente alla variazione

Sfruttando le informazioni fornite dai Mutation record possiamo definire il comportamento della funzione di callback. Ad esempio, il seguente codice visualizza un messaggio sulla console che indica il numero di elementi aggiunti come figli dell'elemento osservato:

var mutationManager = function(mutationRecords) { 
	var i;
	for(i=0; i < mutationRecords.length; i++) {
		if (mutationRecords[i].type == "childList") {
			console.log("Sono stati aggiunti " + mutationRecords[i].addedNodes.length + " elementi.");
		}
	}
};

Se decidiamo di non osservare più le variazioni legate ad un elemento del DOM possiamo utilizzare il metodo disconnect() dell'observer:

observer.disconnect()

Un'ultima importante considerazione riguarda ciò che un Mutation observer è in grado di osservare. Come da definizione, esso può tenere sotto controllo le variazioni della struttura di un sottolabero, la modifica del contenuto o degli attributi di un elemento. Esso non è però in grado di rilevare lo stato interno di un elemento, come ad esempio l'attributo value o checked di un elemento <input>. Quindi in sostanza non possiamo utilizzare un Mutation observer per monitorare le variazioni degli elementi di una form determinati dall'input dell'utente.

Mutation Event, l'alternativa deprecata

Esiste un altro approccio per intercettare le variazioni di struttura e contenuto del DOM e consiste nello sfruttare i Mutation event, una serie di eventi generati dal browser proprio al verificarsi di questo tipo di variazioni.

Purtroppo questo approccio presenta alcuni problemi che possono pregiudicare sensibilmente le prestazioni del browser, tanto da portare il W3C a deprecarli. Ne parliamo in questa guida solo per dare maggior completezza.

Possiamo riassumere i principali difetti dei Mutation event nei seguenti punti:

  • sono eventi sincroni, quindi in presenza di numerose variazioni del DOM la coda degli eventi può riempirsi ad un punto tale da rendere il browser non responsivo
  • nella gestione di un Mutation event può essere necessario modificare il DOM generando quindi altri Mutation event in una reazione a catena che può sfociare in un vero e proprio blocco del browser

Ti consigliamo anche