MutationObserver API

Jedním z mých oblíbených webových triků bylo použití CSS a JavaScriptu k detekci vložení a odebrání uzlu DOM, podrobně popsáno v článku Detekce vložení uzlů DOM pomocí JavaScriptu a CSS animací. Technika a příspěvek na blogu byly zveřejněny v době, kdy jsme neměli rozumné API pro detekci takových událostí. V současné době máme MutationObserver , API vytvořené pro efektivní detekci zátěže operací uzlů. Pojďme se podívat!

Základní MutationObserver API

 MutationObserver API je pro mě trochu komplikované, ale zde je základní nastavení:

var observer = new MutationObserver(function(mutations) {
	// For the sake of...observation...let's output the mutation to console to see how this all works
	mutations.forEach(function(mutation) {
		console.log(mutation.type);
	});    
});
 
// Notify me of everything!
var observerConfig = {
	attributes: true, 
	childList: true, 
	characterData: true 
};
 
// Node, config
// In this case we'll listen to all changes to body and child nodes
var targetNode = document.body;
observer.observe(targetNode, observerConfig);

MutationObserver se dá hodně používat , ale rozdělení je:

  • Vytvořte instanci MutationObserver se zpětným voláním pro zpracování jakékoli události, která se mu dostane do cesty
  • Vytvořte sadu možností pro MutationObserver
  • Zavolejte na číslo observe metoda MutationObserver instanci, předat jí uzel, který má naslouchat (..a jeho potomky) a seznam možností.
  • V době, kdy chcete přestat sledovat, zavolejte na disconnect

MutationObserver Možnosti

MDN poskytuje podrobnosti o možnostech pro MutationObserver :

  • childList :Nastavte na hodnotu true, pokud mají být dodrženy přidávání a odebírání podřízených prvků cílového uzlu (včetně textových uzlů).
  • attributes :Nastavte na hodnotu true, pokud mají být pozorovány mutace atributů cíle.
  • characterData Set :na hodnotu true, pokud mají být pozorovány mutace v datech cíle.
  • subtree :Nastavte na hodnotu true, pokud mají být pozorovány mutace nejen na cíl, ale také na jeho potomky.
  • attributeOldValue :Nastavte na hodnotu true, pokud jsou atributy nastaveny na hodnotu true a hodnota atributu cíle předtím, než je potřeba zaznamenat mutaci.
  • characterDataOldValue :Nastavte na hodnotu true, pokud je characterData nastaveno na hodnotu true a data cíle před tím, než je potřeba zaznamenat mutaci.
  • attributeFilter :Nastavte na pole lokálních názvů atributů (bez jmenného prostoru), pokud není třeba dodržet všechny mutace atributů.

To je třeba si uvědomit, když posloucháte jeden uzel a/nebo podřízené uzly!

MutationRecord: MutationObserver Výsledky obslužného programu

Výsledný objekt, když je pozorována mutace, je také podrobně popsán:

  • type (String) :Vrátí atributy, pokud byla mutace mutací atributu, CharacterData, pokud se jednalo o mutaci uzlu CharacterData, a childList, pokud šlo o mutaci stromu uzlů.
  • target (Node) :Vrátí uzel ovlivněné mutací v závislosti na typu. U atributů je to prvek, jehož atribut se změnil. Pro characterData je to uzel CharacterData. Pro childList je to uzel, jehož potomci se změnili.
  • addedNodes (NodeList) :Vrátí přidané uzly. Pokud nebyly přidány žádné uzly, bude prázdný seznam NodeList.
  • removedNodes (NodeList) :Vraťte odstraněné uzly. Pokud nebyly odstraněny žádné uzly, bude prázdný seznam NodeList.
  • previousSibling (Node) :Vrátí předchozího sourozence přidaných nebo odebraných uzlů nebo hodnotu null.
  • nextSibling (Node) :Vrátí dalšího sourozence přidaných nebo odebraných uzlů nebo hodnotu null.
  • attributeName (String) :Vrátí místní název změněného atributu nebo hodnotu null.
  • attributeNamespace (String) :Vrátí jmenný prostor změněného atributu nebo hodnotu null.
  • oldValue (String) :Vrácená hodnota závisí na typu. U atributů je to hodnota změněného atributu před změnou. Pro characterData jsou to data změněného uzlu před změnou. Pro childList má hodnotu null.

Páni. Pojďme se tedy podívat na některé reálné případy použití MutationObserver .

Detekce při vložení uzlu

Případ použití v příspěvku Detect DOM Node Insertions with JavaScript and CSS Animations s detekce vložení uzlů, takže pojďme vytvořit úryvek, který detekuje vložení uzlů:

// Let's add a sample node to see what the MutationRecord looks like
// document.body.appendChild(document.createElement('li'));

{
	addedNodes: NodeList[1], // The added node is in this NodeList
	attributeName: null,
	attributeNamespace: null,
	nextSibling: null,
	oldValue: null,
	previousSibling: text,
	removedNodes: NodeList[0],
	target: body.document,
	type: "childList"
}

Výsledný záznam MutationRecord zobrazuje addedNodes: NodeList[1] , což znamená, že uzel byl přidán někam níže do stromu. type je childList .

Zjistit, kdy je uzel odstraněn

Odstraněním uzlu se zobrazí následující MutationRecord:

// Now let's explore the MutationRecord when a node is removed
// document.body.removeChild(document.querySelector('div'))

{
	addedNodes: NodeList[0],
	attributeName: null,
	attributeNamespace: null,
	nextSibling: text,
	oldValue: null,
	previousSibling: null,
	removedNodes: NodeList[1], // The removed node is in this NodeList
	target: body.document,
	type: "childList"
}

Tato akce také zobrazuje type z childList ale nyní removeNodes nyní má NodeList[1] , NodeList s odstraněným uzlem.

Zjistit změny atributů

Pokud se u kteréhokoli prvku změní atribut, budete o tom rychle vědět; MutationRecord zobrazí:

// What do attribute changes look like?
// document.body.setAttribute('id', 'booooody');

{
	addedNodes: NodeList[0],
	attributeName: "id",
	attributeNamespace: null,
	nextSibling: null,
	oldValue: null,
	previousSibling: null,
	removedNodes: NodeList[0],
	target: body#booooody.document,
	type: "attributes"
}

Všimněte si také, že target zobrazí uzel, pro který byly změněny atributy. oldValue zobrazí původní hodnotu a zatímco normální getAttribute check poskytne vám novou hodnotu atributů.

Přestaňte poslouchat!

Pokud chcete napsat maximálně efektivní aplikaci, budete přidávat posluchače pouze na dobu, kterou potřebujete, a poté je odebírat, až budete hotovi:

observer.disconnect();

MutationObserver instance má disconnect způsob, jak přestat poslouchat. Vzhledem k tomu, že vaše aplikace může mít mnoho a mnoho operací DOM, možná budete chtít odpojit posluchače na dobu, po kterou uživatel interaguje se stránkou.

MutationObserver API se zdá trochu podrobné, ale je výkonné, informativní a nakonec bez hackování. Geniální originální "hack" Daniela Buchnera poskytuje lepší podporu pro přidávání a odstraňování uzlů, ale MutationObserver by měl být pravděpodobně použit, pokud je to možné.