#javascript #dom-events
#javascript #dom-события
Вопрос:
Я создаю библиотеку JS, и один из вариантов использования требует, чтобы я запускал событие при изменении DOM, особенно если это одностраничное приложение, например: панель поиска github После некоторых исследований, с которыми я столкнулся MutationObserver
:
// Dom change event listner
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(function(mutations, observer) {
// fired when a mutation occurs
attachListners();
// ...
});
observer.observe(documentAlias, {
subtree: true,
childList: true
//...
});
Проблема: библиотека, которую я создаю, предназначена для подключения к любому веб-сайту, поэтому я не могу контролировать реализацию html. Я немного обеспокоен тем, что использование наблюдателя мутаций может ввести бесконечный цикл. Видели много вопросов о переполнении стека в одной строке.
Есть ли какой-либо альтернативный / лучший подход? Как я могу безопасно и эффективно обнаруживать обновления / изменения DOM? Или лучше всего использовать mutation observer
Комментарии:
1. Наиболее эффективным подходом является вызов кода, который обновил dom, а не прослушивание изменений самостоятельно. Но, видимо, вы не можете / не хотите этого делать. Итак, какие обновления делает код, который вам нужно обнаружить? О каких изменениях dom мы говорим? Кто подключает библиотеку к своему веб-сайту и как?
2. @Bergi Это строка поиска, которая отображает результат точно так же, как пример github, который я показал выше. Если поиск обновляется при изменении запроса, мне нужно обнаружить эти новые обновленные результаты..
3. Я не знаю, что вы подразумеваете под «панелью поиска», или как это связано с линтером / форматером standardjs, который вы связали в качестве примера (?). Кто обновляет запрос или обновляет результаты и что ваш код делает с ними?
Ответ №1:
MutationObserver, вероятно, ваш лучший выбор. Раньше MutationObserver
были события мутации, но теперь они устарели и не рекомендуются.
Другим (возможно, плохим) вариантом было бы использовать a setTimeout
и периодически проверять DOM на наличие изменений. Но для этого вам потребуется написать функцию, чтобы получить узлы, которые вы хотите проверить, и сравнить текущее значение со старым значением. Это было бы не так эффективно, поскольку вы бы проверяли узлы каждые X миллисекунд, даже если изменений нет.
Вы должны быть в состоянии написать свой код таким образом, чтобы не возникал бесконечный цикл. Если вы получаете бесконечный цикл, вам следует добавить этот код в свой вопрос выше.
Что касается производительности, так MutationObserver
как даст вам старые и новые значения, вы можете сравнить эти значения вместо обхода всего DOM. Например, что-то вроде этого:
let observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
let oldValue = mutation.oldValue;
let newValue = mutation.target.textContent;
if (oldValue !== newValue) {
// do something
}
});
});
observer.observe(document.body, {
characterDataOldValue: true,
subtree: true,
childList: true,
characterData: true
});