Start · Sprachen · JavaScript · Referenz · MutationRecord.type

MutationRecord.type

Eigenschaft

Schreibgeschützter String, der die Art der beobachteten DOM-Änderung angibt: <code>"attributes"</code>, <code>"characterData"</code> oder <code>"childList"</code>.

seit JavaScript Baseline: alle Browser (DOM4, seit ca. 2012) Kategorie: webapi

Signatur

MutationRecord.type

Beschreibung

Die Eigenschaft type eines MutationRecord gibt an, welche Art von Änderung ein MutationObserver festgestellt hat. Sie ist schreibgeschützt und enthält immer genau einen der drei Werte "attributes", "characterData" oder "childList".

Meist ist type der erste Wert, den man im Callback eines MutationObserver prüft. Ein Beobachter bekommt oft mehrere Arten von Änderungen gleichzeitig gemeldet, deshalb unterscheidet man anhand von type, welche anderen Eigenschaften des Datensatzes überhaupt sinnvoll belegt sind:

  • "attributes": Ein Attribut von target hat sich geändert. attributeName, attributeNamespace und, falls attributeOldValue: true gesetzt ist, auch oldValue sind belegt.
  • "characterData": Der Inhalt eines Text-, Comment- oder ProcessingInstruction-Knotens hat sich geändert. target ist dieser Knoten. oldValue ist belegt, falls characterDataOldValue: true gesetzt ist.
  • "childList": Kindknoten wurden hinzugefügt oder entfernt. addedNodes, removedNodes, previousSibling und nextSibling sind belegt.

Welche Typen überhaupt gemeldet werden, legen die Optionen fest, die man an MutationObserver.prototype.observe() übergibt (attributes, characterData, childList, dazu subtree).

Rückgabewert

Typ
"attributes" | "characterData" | "childList"
Beschreibung
Ein String, der die Art der Mutation angibt.

Beispiele

Mutationstypen im Callback unterscheiden

const container = document.createElement('div');
document.body.append(container);

const observer = new MutationObserver((records) => {
  for (const record of records) {
    switch (record.type) {
      case 'childList':
        console.log(`childList: +${record.addedNodes.length} / -${record.removedNodes.length}`);
        break;
      case 'attributes':
        console.log(`attributes: ${record.attributeName} (alt: ${record.oldValue})`);
        break;
      case 'characterData':
        console.log(`characterData: "${record.oldValue}" → "${record.target.data}"`);
        break;
    }
  }
});

observer.observe(container, {
  childList: true,
  attributes: true,
  attributeOldValue: true,
  characterData: true,
  characterDataOldValue: true,
  subtree: true
});

const text = document.createTextNode('Hallo');
container.append(text);
container.className = 'aktiv';
text.data = 'Hallo Welt';
childList: +1 / -0 attributes: class (alt: null) characterData: "Hallo" → "Hallo Welt"

Nur neu eingefügte Elemente verarbeiten (z. B. Lazy-Init)

const initWidget = (el) => {
  el.dataset.initialisiert = 'ja';
  console.log('Widget initialisiert:', el.id);
};

const observer = new MutationObserver((records) => {
  records
    .filter((r) => r.type === 'childList')
    .flatMap((r) => [...r.addedNodes])
    .filter((node) => node instanceof Element && node.matches('.widget'))
    .forEach(initWidget);
});

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

const widget = document.createElement('div');
widget.className = 'widget';
widget.id = 'chart-1';
document.body.append(widget);
Widget initialisiert: chart-1

Änderungen nach Typ zählen mit takeRecords()

const el = document.createElement('p');
document.body.append(el);

const observer = new MutationObserver(() => {});
observer.observe(el, { attributes: true, childList: true });

el.title = 'Info';
el.append('Text');
el.setAttribute('lang', 'de');

// Noch nicht zugestellte Datensätze synchron abholen
const counts = observer.takeRecords().reduce((acc, r) => {
  acc[r.type] = (acc[r.type] ?? 0) + 1;
  return acc;
}, {});

console.log(counts);
observer.disconnect();
{ attributes: 2, childList: 1 }

// Wichtig · Fallstricke

  • Die Schreibweise ist genau festgelegt: "characterData" mit großem D. Ein Vergleich mit "characterdata" trifft nie zu.
  • Der Typ "childList" meldet nur direkte Kinder von target. Mit subtree: true ist target jeweils der Elternknoten, der sich tatsächlich geändert hat, und nicht der beobachtete Wurzelknoten.
  • Ändert man textContent oder innerHTML, erzeugt das einen Datensatz vom Typ "childList" und keinen vom Typ "characterData", weil dabei Knoten ersetzt werden. Den Typ "characterData" lösen nur direkte Änderungen an data oder nodeValue eines Textknotens aus.
  • Setzt man ein Attribut auf denselben Wert, entsteht trotzdem ein Datensatz vom Typ "attributes".
  • type ist schreibgeschützt. Eine Zuweisung wird ignoriert und wirft im Strict Mode einen TypeError.
  • Performance: Beobachtet man große Teilbäume mit subtree: true, kann das sehr viele Datensätze erzeugen. Man sollte deshalb früh nach type filtern und im Callback keine teuren DOM-Abfragen ausführen.
  • Kompatibilität: Die Eigenschaft wird von allen aktuellen Browsern unterstützt. Der Internet Explorer unterstützt sie erst ab Version 11.