Start · Sprachen · JavaScript · Referenz · new MutationObserver()

new MutationObserver()

Methode

Erstellt einen neuen <code>MutationObserver</code>, der die übergebene Callback-Funktion aufruft, sobald sich beobachtete DOM-Knoten ändern.

seit JavaScript Baseline: alle Browser (seit 2012, DOM Living Stan Kategorie: webapi

Signatur

new MutationObserver(callback)

Beschreibung

Der Konstruktor MutationObserver() erzeugt einen Beobachter für Änderungen am DOM-Baum. Direkt nach dem Erzeugen beobachtet er aber noch nichts: Erst wenn Sie observe(target, options) aufrufen, legen Sie fest, welcher Knoten beobachtet wird und welche Art von Änderung zählt (Kindknoten, Attribute, Textinhalt, optional mit dem ganzen Teilbaum).

Der Callback läuft asynchron als Microtask. Änderungen werden gesammelt und gebündelt übergeben, also als Array von MutationRecord-Objekten. Selbst wenn Sie in einer Schleife hundert Knoten einfügen, läuft der Callback deshalb in der Regel nur einmal. Das ist deutlich effizienter als die veralteten Mutation Events (DOMNodeInserted usw.), die synchron und einzeln ausgelöst wurden.

Typische Einsatzfälle sind: auf dynamisch nachgeladene Inhalte reagieren (z. B. in Single-Page-Apps oder Fremd-Widgets), Attributänderungen verfolgen (etwa class oder aria-*), Inhalte in contenteditable-Bereichen überwachen oder warten, bis ein bestimmtes Element im DOM auftaucht.

Eine Instanz kann mehrere Ziele gleichzeitig beobachten. Mit disconnect() beenden Sie alle Beobachtungen. takeRecords() liefert Änderungen, die noch nicht an den Callback übergeben wurden.

Parameter

Name Typ Default Beschreibung
$callback Pflicht (mutations: MutationRecord[], observer: MutationObserver) => void Funktion, die nach DOM-Änderungen aufgerufen wird. Sie erhält ein Array von MutationRecord-Objekten (mit type, target, addedNodes, removedNodes, attributeName, oldValue usw.) und als zweites Argument den Beobachter selbst. Damit kann der Callback z. B. observer.disconnect() aufrufen.

Rückgabewert

Typ
MutationObserver
Beschreibung
Ein neues MutationObserver-Objekt. Es beobachtet erst nach einem Aufruf von observe() etwas.

Beispiele

Neu eingefügte Kindelemente einer Liste protokollieren

const list = document.querySelector('#todo-list');

const observer = new MutationObserver((mutations) => {
  for (const m of mutations) {
    if (m.type === 'childList') {
      m.addedNodes.forEach((node) => {
        if (node.nodeType === Node.ELEMENT_NODE) {
          console.log('Hinzugefügt:', node.textContent);
        }
      });
    }
  }
});

observer.observe(list, { childList: true });

// Änderungen auslösen
const li = document.createElement('li');
li.textContent = 'Milch kaufen';
list.append(li);
Hinzugefügt: Milch kaufen

Attributänderungen mit altem Wert verfolgen

const button = document.querySelector('#theme-toggle');

const observer = new MutationObserver((mutations) => {
  for (const { attributeName, oldValue, target } of mutations) {
    console.log(`${attributeName}: "${oldValue}" → "${target.getAttribute(attributeName)}"`);
  }
});

observer.observe(button, {
  attributes: true,
  attributeFilter: ['class', 'aria-pressed'],
  attributeOldValue: true
});

button.setAttribute('aria-pressed', 'true');
aria-pressed: "false" → "true"

Auf ein Element warten (Promise-Helfer)

const waitForElement = (selector, root = document.body) =>
  new Promise((resolve) => {
    const existing = root.querySelector(selector);
    if (existing) return resolve(existing);

    const observer = new MutationObserver((_, obs) => {
      const el = root.querySelector(selector);
      if (el) {
        obs.disconnect(); // Beobachtung beenden
        resolve(el);
      }
    });
    observer.observe(root, { childList: true, subtree: true });
  });

const dialog = await waitForElement('.cookie-banner');
console.log('Banner gefunden:', dialog.className);
Banner gefunden: cookie-banner

// Wichtig · Fallstricke

  • Asynchron: Der Callback läuft als Microtask und nicht sofort nach der Änderung. Code direkt nach einer DOM-Manipulation sieht den Callback also noch nicht. Mit takeRecords() holen Sie ausstehende Datensätze synchron ab.
  • Endlosschleifen: Wenn der Callback selbst das beobachtete DOM ändert, löst er sich erneut aus. Rufen Sie in dem Fall vorher disconnect() auf oder prüfen Sie die Bedingung sorgfältig.
  • Performance: subtree: true auf document.body kann bei großen, sehr dynamischen Seiten teuer werden. Beobachten Sie möglichst gezielt und nutzen Sie attributeFilter.
  • Mindestens eine der Optionen childList, attributes oder characterData muss gesetzt sein, sonst wirft observe() einen TypeError. Wenn Sie attributeOldValue oder attributeFilter angeben, gilt attributes: true automatisch.
  • Der Konstruktor muss mit new aufgerufen werden. Ohne new gibt es einen TypeError.
  • Beobachter nach Gebrauch mit disconnect() beenden, damit keine unnötige Arbeit anfällt und keine Speicherlecks entstehen.
  • Kompatibilität: Alle modernen Browser unterstützen die API (ab IE 11). Die veralteten Mutation Events sind abgekündigt und sollten nicht mehr verwendet werden.