MutationObserver повідомляє про зміни в DOM: додавання й видалення вузлів, зміну атрибутів чи тексту. Він замінив застарілі й повільні mutation events (DOMNodeInserted), які браузери поступово видаляють (Chrome - з версії 127).
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node instanceof Element) {
node.querySelectorAll('[data-tooltip]').forEach(initTooltip);
if (node.matches('[data-tooltip]')) initTooltip(node);
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
Що можна спостерігати (опції observe):
childList- додавання й видалення дочірніх вузлів;subtree- разом з усіма нащадками, а не лише прямими дітьми;attributes(+attributeFilter: ['class', 'disabled'],attributeOldValue) - зміни атрибутів;characterData- зміни тексту у текстових вузлах.
Як він виконується. Колбек викликається асинхронно, пакетом, як мікрозадача після поточного коду. Сто змін в одному циклі - один виклик з масивом записів. Тому він значно дешевший за старі синхронні події.
Де корисний:
- ініціалізація сторонніх віджетів на вмісті, що з'являється динамічно (підвантаження, Livewire-оновлення,
wire:navigate); - реакція на зміни, які робить чужий код, якого ви не контролюєте;
- автоматичні тести й інструменти доступності, що стежать за змінами сторінки.
Підводні камені:
subtree: trueнаdocument.body- колбек на кожну зміну всієї сторінки. На складних сторінках це відчутно. Спостерігати варто найменший можливий контейнер з мінімумом опцій;- нескінченний цикл: колбек змінює DOM у тій самій області - це породжує нові записи. Потрібна перевірка, чи елемент уже оброблено (наприклад, атрибут-позначка);
- відключення:
observer.disconnect()при знищенні компонента, інакше спостерігач триматиме посилання на вузли.takeRecords()дає змогу забрати ще не доставлені записи перед відключенням; - не для розміру й видимості: для них є
ResizeObserverіIntersectionObserver- зміна розміру не є мутацією DOM.
Альтернатива, якщо ви контролюєте код, що змінює DOM, - викликати ініціалізацію явно чи через власну подію. Спостерігач потрібен саме тоді, коли зміни відбуваються «десь» поза вашим контролем.
Livewire і Alpine самі використовують MutationObserver: Alpine так помічає нові елементи з x-data і ініціалізує їх.