Как работает JavaScript 10 - мониторинг изменений DOM с MutationObserver

внешний интерфейс JavaScript браузер CSS

Пожалуйста, обратитесь к исходному текстуздесь, слегка удалено, в этой статье используетсяМеждународная лицензия Creative Commons Attribution 4.0доля, ПОTroland.

Эта серия постоянно обновляется, адрес GitHub, пожалуйста, проверьтездесь.

Это десятая глава о том, как работает JavaScript.

Сетевые приложения становятся все более сложными на стороне клиента, что вызвано многими факторами, такими как потребность в расширенных взаимодействиях интерфейса для обеспечения более сложных прикладных функций, вычислений в реальном времени и так далее.

Возрастающая сложность веб-приложений делает невозможным определение точного состояния интерфейса в данный момент его жизненного цикла.

Если вы строите какой-то фреймворк или библиотеку, это сложнее, например, вы не можете следить за тем, чтобы DOM отвечал и выполнял какое-то конкретное действие.

Обзор

MutationObserver Это веб-интерфейс, предоставляемый современными браузерами для обнаружения изменений DOM. Вы можете использовать этот интерфейс для прослушивания новых или удаленных узлов, изменений свойств или изменений содержимого текстовых узлов.

Что может быть сделано?

Вы можете использовать удобный интерфейс MutationObserver в следующих ситуациях. Например:

  • Уведомляет пользователя о некоторых изменениях на странице, на которой он сейчас находится.
  • Динамически загружайте модули JavaScript на основе изменений DOM с помощью некоторых отличных фреймворков JavaScript.
  • Возможно, когда вы разрабатываете WYSIWYG-редактор, используйте интерфейс MutationObserver для сбора изменений в любой момент времени, чтобы легко реализовать функцию отмены/повторения.

Это всего лишь несколько сценариев использования MutationObserver.

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

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

var mutationObserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation);
  });
});

Созданный экземпляр объекта имеет три метода:

  • observe- Начать мониторинг. Принимает два параметра — узел DOM для наблюдения и объект конфигурации.
  • disconnect- Перестаньте слушать изменения.
  • takeRecords- Возвращает последнее изменение пакетных DOM перед запуском обратного вызова.

Ниже приведен фрагмент кода, который начинает прослушивание:

// 开始监听页面根元素 HTML 变化。
mutationObserver.observe(document.documentElement, {
  attributes: true,
  characterData: true,
  childList: true,
  subtree: true,
  attributeOldValue: true,
  characterDataOldValue: true
});

Теперь предположим, что вы написали простуюdivэлемент:

<div id="sample-div" class="test"> Simple div </div>

Вы можете использовать jQuery для удаления divclassАтрибуты:

$("#sample-div").removeAttr("class");

при звонкеmutationObserver.observe(…)Вы можете начать отслеживать изменения DOM.

Каждый раз, когда DOM изменяется, он будет распечатывать каждыйMutationRecordинформация журнала:

Это изменение производится путем удаленияclassвызвано свойствами.

Наконец, если вы хотите перестать прослушивать изменения DOM, вы можете использовать следующий метод:

// MutationObserver 停止监听 DOM 变化
mutationObserver.disconnect();

Сейчас,MutationObserverСовместимость с браузерами хорошая:

альтернативный метод

Однако преждеMutationObserverшироко не используется. Потом, когда нетMutationObserverКогда и как разработчики решают проблему мониторинга изменений DOM?

Доступно несколько методов:

  • голосование
  • MutationEvents
  • CSS-анимация

голосование

Самый простой и грубый способ — использовать опрос. Используя встроенный в браузер веб-интерфейс setInterval, вы можете создать задание cron для периодической проверки изменений в DOM. Конечно, такой подход может значительно снизить производительность веб-приложений/сайтов.

На самом деле это можно понимать как грязную проверку.Если вы использовали AngularJS, вы должны были видеть проблемы с производительностью, вызванные его грязной проверкой. У меня есть небольшое введение в другой моей серии, вы можете проверить егоздесь.

MutationEvents

Запущен в 2000 годуMutationEvents API. Хотя это работает, каждое отдельное изменение DOM вызывает событие мутации, которое, в свою очередь, может вызвать проблемы с производительностью. Сейчас,MutationEventsИнтерфейс устарел, и все современные браузеры прекратят его поддержку в ближайшем будущем.

Ниже приведеныMutationEventsСовместимость с браузером:

CSS-анимация

полагаться наCSS-анимацияявляется несколько новой альтернативой. Это может показаться немного запутанным. По сути, идея состоит в том, чтобы создать анимацию, которая запускается при добавлении элемента в DOM. Запускается, когда начинается анимация CSSanimationstartСобытие: Предполагая, что вы добавили прослушиватель событий для этого события, вы точно знаете, когда элемент добавляется в DOM. Продолжительность анимации должна быть очень короткой, чтобы она была незаметной для пользователя, т. е. опыт был лучше.

Во-первых, вам нужен родительский элемент, в котором можно прослушивать события добавления узла:

<div id=”container-element”></div>

Для обработки добавления узлов необходимо создать анимацию последовательности ключевых кадров, которая запускается при добавлении узла:

@keyframes nodeInserted { 
 from { opacity: 0.99; }
 to { opacity: 1; } 
}

После создания ключевых кадров примените анимацию к элементам, за которыми нужно следить. Обратите внимание, что короткая продолжительность — анимация будет очень гладкой на стороне браузера (т. е. пользователь не почувствует, как происходит анимация):

#container-element * {
 animation-duration: 0.001s;
 animation-name: nodeInserted;
}

это будетcontainer-elementДобавьте анимацию ко всем дочерним узлам . Когда анимация закончится, вызовите событие вставки.

Нам нужно создать функцию как прослушиватель событий. Внутри функции start должен использоватьevent.animationNameКод проверяет, чтобы убедиться, что это та анимация, которую мы слушаем.

var insertionListener = function(event) {
  // 确保是所监听的动画
  if (event.animationName === "nodeInserted") {
    console.log("Node has been inserted: " + event.target);
  }
}

Привяжите прослушиватели событий к родительским элементам:

document.addEventListener(“animationstart”, insertionListener, false); // standard + firefox
document.addEventListener(“MSAnimationStart”, insertionListener, false); // IE
document.addEventListener(“webkitAnimationStart”, insertionListener, false); // Chrome + Safari

Здесь используется делегирование события.

Поддержка браузера анимации CSS:

По сравнению с вышеперечисленными вариантамиMutationObserverЕсть несколько преимуществ. По сути, он прослушивает все возможные изменения в DOM и работает лучше, потому что запускает обратные вызовы после пакетной обработки изменений DOM. Вкратце,MutationObserverСовместимость хорошая, есть проставки на основеMutationEventsиз.

Реклама ^.^

Сегодняшние заголовки вербуют! Отправить резюме наlikun.liyuk@bytedance.com, вы можете использовать быстрый внутренний push-канал, который эффективен в течение длительного времени! JD в подразделении Internationalized PGC:From.modified.US/board/V5/2H…, вы также можете нажать другие отделы!

Эта серия постоянно обновляется, пожалуйста, обратитесь к адресу Github.здесь.