Migrazione di eventi di mutazione e modifica di proprietà a osservatori di mutazioni

Gli osservatori di mutazioni in Internet Explorer 11 offrono una sostituzione ad alte prestazioni per tutti gli stessi scenari supportati dagli eventi di mutazione e un'alternativa per gli scenari supportati dagli eventi di modifica di proprietà.

Puoi migrare il codice esistente utilizzando eventi di mutazione e/o eventi di modifica delle proprietà per l'uso di osservatori di mutazioni.

Tecniche legacy per il monitoraggio delle mutazioni DOM

Mutation events hanno un ruolo chiave nella piattaforma Web. Consentono alle app Web di monitorare in modo sincrono le modifiche dinamiche agli elementi DOM (Document Object Model) di una pagina Web. Nonostante la loro utilità, gli eventi di mutazione determinano una regressione delle prestazioni delle app, soprattutto a causa della loro natura sincrona e dell'architettura di eventi su cui si basano.

Nota   Gli eventi di mutazione (definiti in W3C DOM Level 3 Events) sono stati deprecati e sostituiti dagli osservatori di mutazioni (W3C DOM4).

Gli eventi di modifica delle proprietà forniscono un comportamento simile agli eventi di mutazione, ma determinano anch'essi un calo di prestazioni, perché per funzionare correttamente devono utilizzare il sistema di eventi legacy del browser.

Nota  L'evento onpropertychange è supportato solo con il modello di registrazione eventi legacy attachEvent esclusivo per IE, che è deprecato a partire da Windows Internet Explorer 9 (e non è più disponibile in IE11) a favore del modello di eventi standard W3C "addEventListener".

Identificazione degli eventi di mutazione

Gli eventi di mutazione, disponibili per la prima volta in Internet Explorer 9, possono essere facilmente identificati in base al relativo nome, che è un parametro stringa passato alle API di piattaforma addEventListener o removeEventListener:

  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMSubtreeModified
  • DOMAttrModified
  • DOMCharacterDataModified

Nota  Lo standard definisce altri due eventi di mutazione, che non sono tuttavia supportati da Internet Explorer: DOMNodeInsertedIntoDocument e DOMNodeRemovedFromDocument.

Ecco un esempio dell'aspetto che potrebbe avere uno di questi eventi nel codice JavaScript:


someElement.addEventListener("DOMAttrModified", function() {
  //...
}, false);

Gli eventi di mutazione DOMNodeInserted, DOMNodeRemoved e DOMSubtreeModified monitorano le modifiche strutturali agli elementi figlio di un elemento (se vengono aggiunti o rimossi elementi tra i figli dell'elemento). L'evento DOMSubtreeModified può essere utilizzato per entrambi, poiché viene generato per rimozioni e aggiunte, ma non contiene alcuna informazione relativa al motivo per cui è stato generato (non è possibile distinguere un'aggiunta da una rimozione in base al singolo evento).

L'evento di mutazione DOMAttrModified segnala le modifiche all'elenco di attributi di un elemento. Questo singolo evento include informazioni relative a inserimenti, rimozioni o modifiche di attributi.

L'evento di mutazione DOMCharacterDataModified segnala le modifiche al contenuto di testo di un elemento. Il contenuto di testo è raggruppato in unità logiche denominate nodi di testo e solo le modifiche a un nodo di testo esistente generano l'evento DOMCharacterDataModified. L'inserimento o la creazione di nuovi nodi di testo viene invece segnalata come evento DOMNodeInserted.

Individuare gli eventi di mutazione nel codice è semplice, poiché in genere basta usare la funzione di ricerca nei file del proprio editor preferito. Tieni presente che spesso vengono usate variabili nel metodo addEventListener, pertanto assicurati di cercare prima l'uso delle stringhe degli eventi di mutazione ("DOMNodeInserted", "DOMNodeRemoved" e così via) e quindi di controllare tutte le occorrenze di addEventListener per verificare di averle individuate tutte.

Identificazione degli eventi di modifica di proprietà

Gli eventi di modifica delle proprietà possono essere identificati in base al nome dell'evento onpropertychange usato insieme all'API di registrazione degli eventi legacy attachEvent o detachEvent esclusiva per IE. Per trovare gli eventi di questo tipo utilizzati nel codice, individua tutte le occorrenze di attachEvent e cerca onpropertychange nel primo parametro.

L'evento di modifica delle proprietà viene generato quando le proprietà di un elemento DOM vengono modificate. L'evento non esegue il bubbling ed è stato deprecato a partire da Internet Explorer 9, a favore del modello di eventi standard W3C "addEventListener". L'evento include il nome della proprietà che è stata modificata nel getter propertyName degli eventi. Sfortunatamente, per l'invio di un evento di modifica delle proprietà vengono calcolati anche molti altri attributi di evento, alcuni dei quali forzano il ricalcolo da parte del motore di layout, causando un sostanziale costo in termini di prestazioni per qualsiasi applicazione che usa questi eventi.

Unlike with mutation events, l'evento di modifica delle proprietà non viene mappato in modo pulito agli osservatori di mutazioni. È comunque possibile sostituire l'uso degli eventi di modifica delle proprietà con osservatori di mutazioni se gli attributi HTML riflettono i nomi delle proprietà. Ad esempio, id, che riflette l'attributo id, style.color che è riflesso nell'attributo style serializzato e className che corrisponde all'attributo class.

Nota  Per le proprietà non riflesse negli attributi HTML (ad esempio value su elementi input), è possibile utilizzare la funzionalità ECMAScript 5 (JavaScript) denominata defineProperty. In questo documento non viene descritto come eseguire la migrazione degli eventi di modifica delle proprietà tramite l'API Object.defineProperty JavaScript .

Differenze degli osservatori di mutazioni

Gli osservatori di mutazioni non sono basati sul modello di eventi della piattaforma Web. Questa differenza è molto importante, poiché consente di inviarli molto più velocemente e senza effettuare il bubbling di un evento attraverso la gerarchia di elementi DOM.

Inoltre, gli osservatori di mutazioni sono progettati per registrare più modifiche prima di avvisare l'osservatore. Accumulano infatti i record di mutazione per evitare di inviare all'applicazione un numero di eventi eccessivo. Viceversa, gli eventi di mutazione sono sincroni e interrompono la normale esecuzione del codice per segnalare le mutazioni all'applicazione. Nonostante il modello di notifica ritardato impiegato dagli osservatori di mutazioni, gli osservatori dell'applicazione ricevono (e hanno la possibilità di elaborare) tutti i record di mutazione prima dell'aggiornamento successivo.

Entrambe queste modifiche influiscono sul modo in cui deve essere adattata l'app per supportare gli osservatori di mutazioni.

Registrazione degli osservatori di mutazioni

È necessario creare gli osservatori di mutazioni prima di poterli registrare per un determinato elemento. Per creare un osservatore di mutazioni, usa l'operatore JavaScript new e specifica un metodo di callback:


var mutationObserver = new MutationObserver(callback);

Il callback fornito al costruttore dell'osservatore di mutazioni sarà diverso da quello probabilmente usato per gli eventi di mutazione correnti. Questo aspetto verrà illustrato in dettaglio più avanti.

Dopo avere creato l'osservatore, devi istruirlo per l'osservazione di un particolare elemento. In genere, questo sarà lo stesso elemento su cui in precedenza hai registrato l'evento di mutazione:


mutationObserver.observe(someElement, options);

Se non salvi un riferimento all'osservatore, l'istanza dell'osservatore di mutazioni verrà preservata in memoria dalla piattaforma Web finché osserva almeno un elemento. Se non salvi un riferimento all'osservatore, puoi comunque farvi riferimento dal callback dell'osservatore (sarà l'oggetto this nell'ambito del callback, oltre che il secondo parametro della funzione di callback).

Il parametro per le opzioni è un semplice oggetto JavaScript con proprietà che devi fornire per descrivere esattamente i tipi di mutazioni che desideri osservare. Le opzioni delle proprietà corrispondono alle tre categorie di mutazioni descritte in precedenza:

  • childList
  • attributes
  • characterData

L'opzione childList con un valore true indica di osservare le modifiche agli elementi figlio di questo elemento (rimozioni e aggiunte). Questa opzione include i nodi di testo aggiunti o rimossi come figli di questo elemento.

L'opzione attribute con un valore true indica di osservare le modifiche agli attributi di questo elemento (rimozioni, aggiunte e modifiche).

L'opzione characterData con un valore true indica di osservare le modifiche ai nodi di testo di questo elemento (modifiche dei valori dei nodi di testo, tranne quando vengono rimossi o aggiunti nodi di testo).

È anche importante una quarta opzione, subtree. Le tre opzioni precedenti (per impostazione predefinita) osservano solo l'elemento di destinazione in modo isolato, senza considerarne i discendenti (il relativo sottoalbero). Per monitorare l'elemento specificato e tutti i relativi discendenti, imposta la proprietà subtree su true. Poiché gli eventi di mutazione effettuano il bubbling attraverso il DOM, è necessario utilizzare l'opzione subtree per mantenere la parità con gli eventi di mutazione registrati negli elementi predecessori.

Nella tabella seguente sono descritte le opzioni degli osservatori di mutazioni che corrispondono ai nomi degli eventi di mutazione:

Evento di mutazione Opzioni degli osservatori di mutazioni Note
DOMNodeInserted { childList: true, subtree: true } Il callback deve ignorare manualmente i record di rimozione di nodi
DOMNodeRemoved { childList: true, subtree: true } Il callback deve ignorare manualmente i record di aggiunta di nodi
DOMSubtreeModified { childList: true, subtree: true } Il callback ora può distinguere tra nodi aggiunti e rimossi
DOMAttrModified { attributes: true, subtree: true }
DOMCharacterDataModified { characterData: true, subtree: true }

 

Nota  Gli osservatori di mutazioni consentono inoltre di combinare più opzioni per osservare contemporaneamente childLists, attributes e characterData.

Sono infine disponibili diverse opzioni per il salvataggio dei valori di attributi precedenti e delle modifiche dei dati dei caratteri, oltre che per perfezionare l'ambito degli attributi che è importante osservare:

  • Le opzioni attributeOldValue e characterDataOldValue con un valore di true salvano il valore precedente quando si verificano modifiche di attributi o characterData.
  • L'opzione attributeFilter con una matrice di stringhe di nomi di attributi limita l'osservazione agli attributi specificati. Questa opzione è applicabile solo quando l'opzione attributes è impostata su true.

Con queste informazioni, qualsiasi codice registrato in precedenza per un evento di mutazione può essere sostituito con codice che esegue la registrazione per un osservatore di mutazioni:


// Watch for all changes to the body element's children
document.body.addEventListener("DOMNodeInserted", nodeAddedCallback, false);
document.body.addEventListener("DOMNodeRemoved", nodeRemovedCallback, false);


Ora diventa:


// Watch for all changes to the body element's children
new MutationObserver(nodesAddedAndRemovedCallback).observe(document.body, 
  { childList: true, subtree: true });


Callback degli osservatori di mutazioni

La funzione di callback dell'osservatore di mutazioni viene richiamata con due parametri:

  • Un elenco di record
  • Un riferimento all'oggetto dell'osservatore di mutazioni che richiama la funzione di callback

Presta attenzione se riutilizzi callback di eventi di mutazione per osservatori di mutazioni. Quando si verifica una mutazione rilevante, MutationObserver registra le informazioni sulla modifica richieste in un oggetto MutationRecord e richiama la funzione di callback, ma solo dopo l'esecuzione di tutti gli script nell'ambito corrente. È possibile che si verifichi più di una mutazione (ognuna rappresentata da un singolo MutationRecord) dall'ultima volta che è stata richiamata la funzione di callback.

Il parametro records è una matrice JavaScript composta da oggetti MutationRecord. Ogni oggetto nella matrice rappresenta una mutazione che si è verificata su uno o più elementi sottoposti a osservazione.

Gli elementi records presentano le seguenti proprietà:

Proprietà MutationRecord Descrizione

type

Tipo di mutazione registrata dal record. Possibili valori: attributes, characterData, childList.

target

Elemento per cui è stata registrata la mutazione. Simile a event.target o event.srcElement.

addedNodes, removedNodes

Matrice di nodi aggiunti o rimossi nell'ambito della mutazione, applicabile solo quando type è childList. Queste matrici possono essere vuote.

previousSibling, nextSibling

Elementi di pari livello precedenti e successivi del nodo aggiunto o rimosso; applicabile solo quando type è childList. Questi valori possano essere null.

attributeName, attributeNamespace

Nome e spazio dei nomi dell'attributo aggiunto, rimosso o modificato. Il valore sarà null se il tipo di record non è attributes.

oldValue

Valore precedente dell'attributo o characterData. Il valore può essere null se le opzioni dell'osservatore di mutazioni non includevano i flag attributeOldValue o characterDataOldValue oppure se type è childList.

 

 

 

Mostra:
© 2014 Microsoft