Détecter les modifications DOM avec des observateurs de mutation

En 2000, l'API Mutation Events a été spécifiée pour permettre aux développeurs de réagir facilement aux modifications apportées à un DOM (DOMNodeRemoved, DOMAttrModified, etc.).

Cette fonctionnalité n'était pas largement utilisée par les développeurs Web, mais elle représentait un cas d'utilisation très pratique et populaire pour les extensions Chrome lorsqu'ils souhaitaient effectuer une action lorsqu'un élément de la page changeait.

Les événements de mutation sont utiles, mais ils créent également des problèmes de performances. Les événements sont lents et sont déclenchés trop fréquemment de manière synchrone, ce qui entraîne des bugs de navigateur indésirables.

Introduits dans la spécification DOM4, les observateurs de mutation DOM remplaceront les événements de mutation. Alors que les événements de mutation déclenchaient des événements lents pour chaque modification, les observateurs de mutations sont plus rapides grâce à des fonctions de rappel pouvant être envoyées après plusieurs modifications dans le DOM.

Vous pouvez gérer manuellement la liste des modifications proposées par l'API ou utiliser une bibliothèque telle que Mutation Summary, qui facilite cette tâche et ajoute une couche de fiabilité aux modifications apportées au DOM.

Vous pouvez commencer à utiliser les observateurs de mutation dans la version bêta de Chrome pour détecter les modifications dans le DOM et être prêt à les utiliser lorsqu'ils seront disponibles dans la version stable (Chrome 18). Si vous utilisez actuellement les événements de mutation obsolètes, migrez simplement vers les observateurs de mutations.

Voici un exemple de liste de nœuds insérés avec des événements de mutation:

var insertedNodes = [];
document.addEventListener("DOMNodeInserted", function(e) {
    insertedNodes.push(e.target);
}, false);
console.log(insertedNodes);

Voici à quoi cela ressemble avec les observateurs de mutations:

var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
    for (var i = 0; i < mutation.addedNodes.length; i++)
        insertedNodes.push(mutation.addedNodes[i]);
    })
});
observer.observe(document.documentElement, { childList: true });
console.log(insertedNodes);