СвязатьсяНачать
Вернуться в блог
17.01.2024
JavaScript

Mutation Observer или как следить за изменением CSS класса

Достаточно часто сейчас нужно добавлять свои куски кода в чужой код, к которому у вас нет никакого доступа. От этого требование — дописывать отдельно на чистом JS.

Сегодня поговорим про божественный API Mutation Observer.

Предисловие

Мне достаточно часто нужно добавить свои куски кода в чужой код, к которому я не имею ни малейшего доступа. Или это готовый плагин/тема в WordPress с компилированным JS кодом в один файл, где нормально прочитать код просто не получается. От этого требование — дописывать отдельно на чистом JS. И часто нужно выполнить свою функцию, как только что-то определенное изменится на странице.

Например, кто-то уже сделал функционал который срабатывает при клике\скролле\ховере\etc. Логика там достаточно сложная, написана в чужом коде, который вы не можете редактировать. И вам нужно по этой же логике просто добавить свой мини-функционал. Чтобы не повторять чужую логику, вы можете следить за изменением DOM-объекта, и привязаться уже к этим изменениям! Самый простой пример: следить за изменением CSS (HTML) класса DOM-объекта.

Функция

Если класс у объекта .search-trigger изменился — добавить к <body> класс .noscroll. Если класс у объекта .search-trigger изменился назад на .search-trigger — удаляем класс .noscroll у <body>.

var mutationObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation);
    console.log(mutation.oldValue);
    if (mutation.oldValue === 'search-trigger') {
      document.getElementsByTagName('body')[0].classList.add('noscroll');
    } else {
      document.getElementsByTagName('body')[0].classList.remove('noscroll');
    }
  });
});

// Starts listening for changes in the '.search-trigger' HTML element
mutationObserver.observe(document.querySelector('.search-trigger'), {
  attributes: true,
  characterData: true,
  childList: true,
  subtree: true,
  attributeOldValue: true,
  characterDataOldValue: true
});

Тут я почему-то слежу за старым значением (mutation.oldValue), но можно следить напрямую за классом:

mutation.target.classList.contains('active');

Очень простая APIшка, очень полезная, всем рекомендую.