MutationObserver

23-04-26 17:08:33


Image for the MutationObserver

Что такое MutationObserver и зачем он нужен

Представь, что у тебя есть страница, где элементы могут изменяться динамически (например, чат, список задач или UI после API-запроса). Иногда нужно отследить эти изменения и выполнить код.
Раньше для этого использовали события вроде DOMNodeInserted, но они устарели и плохо работают.
MutationObserver — это современный и эффективный способ отслеживать изменения DOM.

Базовая идея

Ты создаешь «наблюдателя», говоришь ему:

  • за каким элементом следить
  • какие изменения отслеживать

И он вызывает callback, когда что-то меняется.

Пример

Допустим, мы хотим отследить добавление элементов в список:

<ul id="list"></ul>
const target = document.getElementById('list');

// создаем observer
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
console.log('Произошло изменение:', mutation);
}
});

// настраиваем, что именно отслеживать
observer.observe(target, {
childList: true // отслеживать добавление/удаление дочерних элементов
});

// добавим элемент
const li = document.createElement('li');
li.textContent = 'Новый элемент';
target.appendChild(li);

В консоли ты увидишь сообщение о том, что элемент добавлен.

Какие изменения можно отслеживать

Основные опции:

observer.observe(target, {
childList: true, // добавление/удаление элементов
attributes: true, // изменения атрибутов
characterData: true, // изменения текста
subtree: true // следить за всеми потомками
});

Примеры

Отслеживание изменения атрибутов

<div id="box"></div>
const box = document.getElementById('box');

const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes') {
​ console.log(`Атрибут ${mutation.attributeName} изменен`);
}
});
});

observer.observe(box, {
attributes: true
});

// меняем атрибут
box.setAttribute('class', 'active');

Отслеживание текста

​<p id="text">Привет</p>
const textNode = document.getElementById('text').firstChild;

const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
console.log('Текст изменился:', mutation.target.data);
});
});

observer.observe(textNode, {
characterData: true
});

// изменение текста
textNode.data = 'Привет мир';

Остановка наблюдения

Если больше не нужно следить за изменениями — обязательно отключай observer:

observer.disconnect();

Это важно для:

  • производительности
  • избежания утечек памяти

Когда использовать MutationObserver

Используй его, когда:

  • DOM меняется динамически (React/Vue без прямого доступа)
  • нужно отследить сторонние изменения (например, виджет)
  • работаешь с legacy кодом или сторонними библиотеками

Когда НЕ стоит использовать

Не используй, если:

  • ты сам контролируешь изменения (лучше просто вызвать функцию напрямую)
  • можно использовать события (например, click, input)

Частые ошибки

Следить за всем DOM

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

Это может сильно нагрузить браузер.

Забывать disconnect

Observer продолжает работать → утечки памяти.

Не фильтровать изменения

Всегда проверяй mutation.type, иначе будешь обрабатывать лишнее.

Итог

MutationObserver — мощный инструмент, который:

  • отслеживает изменения DOM
  • работает асинхронно и эффективно
  • заменяет устаревшие DOM-события

Но важно использовать его аккуратно, чтобы не убить производительность.