Ответ 1
Можно наблюдать только существующий node.
Но не беспокойтесь, поскольку getElementById безумно быстро по сравнению с перечислением всех добавленных узлов мутаций, ожидая появления элемента, не будет облагаться налогом вообще, как вы увидите на панели Devtools → Profiler.
function waitForAddedNode(params) {
new MutationObserver(function(mutations) {
var el = document.getElementById(params.id);
if (el) {
this.disconnect();
params.done(el);
}
}).observe(params.parent || document, {
subtree: !!params.recursive,
childList: true,
});
}
Использование:
waitForAddedNode({
id: 'message',
parent: document.querySelector('.container'),
recursive: false,
done: function(el) {
console.log(el);
}
});
Всегда используйте профилировщик devtools и пытайтесь заставить обратный вызов наблюдателя потреблять менее 1% времени процессора.
- По возможности наблюдайте прямых родителей будущего node (
subtree: false
) - Используйте getElementById, getElementsByTagName и getElementsByClassName внутри обратного вызова MutationObserver, избегайте querySelector и особенно чрезвычайно медленного querySelectorAll.
- Если querySelectorAll абсолютно неизбежен в обратном вызове MutationObserver, сначала выполните проверку querySelector, в среднем такая комбо будет намного быстрее.
- Не используйте методы Array, такие как forEach, filter и т.д., которые требуют обратных вызовов внутри обратного вызова MutationObserver, потому что в Javascript функция invocation является дорогостоящей операцией по сравнению с классическим циклом
for (var i=0 ....)
, а обратный вызов MutationObserver может срабатывать 100 раз в секунду, десятки, сотни или тысячиaddedNodes
в каждой партии мутаций на сложных современных страницах. - Не используйте медленные циклы ES2015, например
for (v of something)
внутри обратного вызова MutationObserver, если вы не перекомпилируете, а результирующий код работает так же быстро, как классическийfor
.