Поведение mutationobserver'а после того, как элемент был удален
У меня есть MutationObserver
привязанный к элементу html #foo
.
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// ...
});
});
Когда пользователь нажимает #button
элемент, #foo
удаляется и появляется снова через секунду.
<div id="button">Click me to remove the Foo!</div>
<div id="foo">Hello, I'm Foo!</div>
И, как я заметил, после того, как #foo
был удален и воссоздан, наблюдатель перестал работать.
- это нормальное поведение?
- Итак, мне нужно снова запустить наблюдателя?
И третий вопрос:
- является ли первый наблюдатель полностью удаленным? Или, вместо этого, он все еще бежит, просто "ничего не делая"? - Я спрашиваю об этом, потому что не хочу, чтобы несколько наблюдателей бежали, если только один из них делает реальную работу.
1 ответ:
Поведение будет полностью зависеть от того, что вы подразумеваете под этим.И появляется снова через секунду
Если вы имеете в видуновый элемент с тем же
id
создается, то да, это ожидаемое поведение: когда вы вызываетеobserver.observe
на элемент, вы вызываете его наэтот конкретный элемент , а не любой элемент, соответствующий его ID. Если вы удалите этот элемент из DOM и замените его другим, другим элементом, который выглядит одинаково, наблюдатель будет не магически подключенный к этому новому, отличному элементу:
var target = document.querySelector("#foo"); var observer = new MutationObserver(function(mutations) { snippet.log("#foo was modified"); }); observer.observe(target, {subTree: true, childList: true}); var counter = 0; tick(); setTimeout(function() { snippet.log("Replacing foo with a new one"); target.parentNode.removeChild(target); target = document.createElement("div"); target.id = "foo"; target.innerHTML = "This is the new foo"; document.body.insertBefore(target, document.body.firstChild); }, 1000); function tick() { target.appendChild(document.createTextNode(".")); if (++counter < 20) { setTimeout(tick, 200); } }
<div id="foo">This is the original foo</div> <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Если вы имеете в виду, что вы возвращаете тот же элемент обратно в DOM, то нет, это не будет ожидаемым поведением, а не тем, что происходит в этом примере:
var target = document.querySelector("#foo"); var observer = new MutationObserver(function(mutations) { snippet.log("#foo was modified"); }); observer.observe(target, {subTree: true, childList: true}); var counter = 0; tick(); setTimeout(function() { snippet.log("Removing foo for a moment"); target.parentNode.removeChild(target); setTimeout(function() { snippet.log("Putting the same foo back in"); document.body.insertBefore(target, document.body.firstChild); }, 100); }, 1000); function tick() { target.appendChild(document.createTextNode(".")); if (++counter < 20) { setTimeout(tick, 200); } }
Ключевое сообщение здесь заключается в том, что наблюдатель наблюдает за одним конкретным элементом, который вы передаете в<div id="foo">This is the original foo</div> <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
observe
.
Эти вопросы применимы только в том случае, если вы удаление старого элемента и замена его на совершенно новый:
Если вы удаляете исходный элемент и ставите на его место Новый, вы должны сказать наблюдателю, чтобы он прекратил наблюдение:Итак, мне нужно снова запустить наблюдателя?
Если у вас есть новый элемент, вы можете подключить к нему наблюдателя:observer.disconnect();
observer.observe(theNewElement, /*...options go here...*/);
Является ли первый наблюдатель полностью удаленным? Или, вместо этого, он все еще работает, просто " делая ничего"?
В теории , так как спецификация ясно показывает, что это элемент, который имеет ссылку на своих наблюдателей, то если вы отпустите свою единственную ссылку на элемент, в теории наблюдатель отключается, потому что элемент и его список наблюдателей очищаются. Однако неясно, как метод наблюдателя
disconnect
может быть реализован без того, чтобы у наблюдателя была ссылка на элемент, поэтому они могут иметь взаимные ссылки. Если ты продолжишь ваша ссылка на наблюдателя, которая сохранит взаимные ссылки в памяти. Я бы отключил его специально, чтобы быть уверенным.Я спрашиваю об этом, потому что не хочу, чтобы несколько наблюдателей бежали, если только один из них делает реальную работу.Наблюдатели не "бегут", они реагировать. Наблюдатель будет продолжать наблюдать исходный элемент до тех пор, пока вы не отключите его. Если вы ничего не делаете с исходным элементом, наблюдатель ничего не делает. ничего другого, чем принимать до памяти. Но опять же, если вы собираетесь удалить элемент, вы должны отключить наблюдателя.