Start · Sprachen · JavaScript · Referenz · MutationObserver.observe()

MutationObserver.observe()

Methode

Startet die Beobachtung eines DOM-Knotens und legt fest, welche Änderungen (Kindknoten, Attribute, Textinhalt) den Callback des <code>MutationObserver</code> auslösen.

seit JavaScript Baseline: alle Browser (DOM Living Standard) Kategorie: webapi

Signatur

MutationObserver.prototype.observe(target, options)

Beschreibung

Mit observe() meldest du einen MutationObserver an einem Zielknoten an. Ab diesem Moment sammelt der Browser alle passenden Änderungen als MutationRecord-Objekte und übergibt sie gebündelt an den Callback, der im Konstruktor angegeben wurde. Die Zustellung erfolgt asynchron als Microtask, also nach dem aktuell laufenden Skript, aber vor dem nächsten Rendern.

Über das options-Objekt legst du fest, was beobachtet wird: Hinzufügen und Entfernen von Kindknoten (childList), Attributänderungen (attributes), Änderungen an Textknoten (characterData) und ob der gesamte Unterbaum einbezogen wird (subtree). Mindestens eine der Optionen childList, attributes oder characterData muss am Ende true sein, sonst wirft die Methode einen TypeError.

Typische Einsatzfälle sind: auf dynamisch nachgeladene Inhalte reagieren (z. B. von Drittanbieter-Skripten), Widgets initialisieren, sobald ihr Element im DOM auftaucht, Attributänderungen wie class oder aria-* verfolgen oder Editoren mit contenteditable überwachen. Ein Observer kann mehrere Ziele beobachten, indem du observe() mehrfach aufrufst. Wird derselbe Knoten erneut beobachtet, ersetzen die neuen Optionen die alten.

Parameter

Name Typ Default Beschreibung
$target Pflicht Node Der DOM-Knoten (Element, Textknoten, Document …), der beobachtet werden soll. Mit subtree: true gilt die Beobachtung auch für alle Nachfahren.
$options MutationObserverInit {} Konfigurationsobjekt mit folgenden Eigenschaften:
  • childList (boolean): Hinzufügen/Entfernen von Kindknoten melden.
  • attributes (boolean): Attributänderungen melden. Wird automatisch true, wenn attributeFilter oder attributeOldValue gesetzt ist.
  • characterData (boolean): Änderungen an Textinhalten melden. Wird automatisch true, wenn characterDataOldValue gesetzt ist.
  • subtree (boolean): Den gesamten Unterbaum von target einbeziehen.
  • attributeFilter (string[]): Nur diese Attributnamen beobachten.
  • attributeOldValue (boolean): Vorherigen Attributwert in record.oldValue liefern.
  • characterDataOldValue (boolean): Vorherigen Textinhalt in record.oldValue liefern.
Mindestens eine von childList, attributes oder characterData muss (direkt oder implizit) aktiv sein.

Beispiele

Neu eingefügte Listeneinträge erkennen

const liste = document.querySelector('#nachrichten');

const observer = new MutationObserver((records) => {
  for (const record of records) {
    for (const node of record.addedNodes) {
      if (node.nodeType === Node.ELEMENT_NODE) {
        console.log('Neuer Eintrag:', node.textContent);
      }
    }
  }
});

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

// Simuliert nachgeladenen Inhalt
const li = document.createElement('li');
li.textContent = 'Hallo Welt';
liste.append(li);
Neuer Eintrag: Hallo Welt

Bestimmte Attribute mit altem Wert verfolgen

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

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

// attributes: true ist durch attributeFilter implizit gesetzt
observer.observe(button, {
  attributeFilter: ['aria-expanded', 'class'],
  attributeOldValue: true
});

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

Warten, bis ein Element im DOM erscheint (Promise-Helfer)

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

    const observer = new MutationObserver(() => {
      const el = root.querySelector(selector);
      if (el) {
        observer.disconnect(); // Beobachtung beenden, Speicher freigeben
        resolve(el);
      }
    });

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

const main = async () => {
  const widget = await warteAufElement('.chat-widget');
  console.log('Widget gefunden:', widget.className);
};
main();

setTimeout(() => {
  const div = document.createElement('div');
  div.className = 'chat-widget';
  document.body.append(div);
}, 500);
Widget gefunden: chat-widget

Textänderungen in einem contenteditable-Bereich

const editor = document.querySelector('[contenteditable]');

const observer = new MutationObserver((records) => {
  const textAenderungen = records.filter((r) => r.type === 'characterData');
  console.log(`${textAenderungen.length} Textänderung(en)`);
});

observer.observe(editor, {
  characterData: true,
  characterDataOldValue: true,
  childList: true,
  subtree: true
});

// Später, z. B. beim Verlassen der Seite:
// observer.disconnect();

// Wichtig · Fallstricke

  • TypeError: Wirft einen Fehler, wenn weder childList, attributes noch characterData aktiv ist, oder wenn attributeOldValue/attributeFilter mit explizitem attributes: false kombiniert wird (analog für characterDataOldValue).
  • Performance: { childList: true, subtree: true } auf document.body kann auf großen, dynamischen Seiten sehr viele Records erzeugen. Beobachte möglichst eng begrenzte Knoten, nutze attributeFilter und halte den Callback schlank.
  • Endlosschleifen: Änderst du im Callback das beobachtete DOM, löst das erneut Mutationen aus. Vorher disconnect() aufrufen oder Änderungen per Bedingung absichern.
  • Asynchron: Der Callback läuft als Microtask, mehrere Änderungen werden gebündelt. Wer synchron ausstehende Records braucht, nutzt takeRecords().
  • Entfernte Knoten: Bei subtree: true werden Änderungen in einem entfernten Teilbaum weiterhin gemeldet, bis der Observer die entfernten Knoten nicht mehr verfolgt (bis zur nächsten Zustellung).
  • Observer werden nicht automatisch beendet – mit disconnect() aufräumen, um Speicherlecks zu vermeiden. Shadow DOM-Inhalte werden nicht über den Host erfasst; den ShadowRoot separat beobachten.
  • Kompatibilität: In allen modernen Browsern verfügbar (ab IE 11); ersetzt die veralteten Mutation Events wie DOMNodeInserted.