Похоже, когда наблюдаемый контейнер имеет свой набор innerHTML
, дочерние элементы контейнера очищаются, а затем добавляются новые дочерние элементы полностью неповрежденными . Используя синхронного наблюдателя (просто чтобы вы могли видеть, что происходит), посмотрите, как существуют дочерние узлы при добавлении элемента:
// Look at results in browser console:
window.addEventListener('DOMNodeInserted', (e) => {
console.log(e.path[0].childNodes.length);
});
document.querySelector('#frame').innerHTML = document.querySelector('#template').innerHTML
<div id="frame"></div>
<div id="template" style="display: none;">
<div class="level-1">
<div class="level-2">
<div id="nested">
I exist in the DOM but am not being seen by the MutationObserver
</div>
</div>
</div>
<div class="level-1">
<div class="level-2">
</div>
</div>
<div class="level-1">
<div class="level-2">
</div>
</div>
</div>
Внук наблюдаемого контейнера прикрепляется к дочернему элементу до того, как дочерний элемент прикрепляется к контейнеру, поэтому subtree: true
не видит действие вложения.
Чтобы обнаружить все дочерние узлы, вставленные таким образом, вам придется рекурсивно перебирать все элементы в MutationRecord вручную, несмотря на subtree: true
.
const recurse = (parent) => {
console.log(parent);
if (parent.childNodes) {
[...parent.childNodes].forEach(recurse);
}
};
const domObserver = new MutationObserver((records) => {
for (const record of records) {
for (const node of record.addedNodes) {
recurse(node);
}
}
})
domObserver.observe(document.querySelector('#frame'), {childList: true, subtree: true})
// copy child nodes out of #template (as a string) and inject them into #frame for the observer to detect
document.querySelector('#frame').innerHTML = document.querySelector('#template').innerHTML
<div id="frame"></div>
<div id="template" style="display: none;">
<div class="level-1">
<div class="level-2">
<div id="nested">
I exist in the DOM but am not being seen by the MutationObserver
</div>
</div>
</div>
<div class="level-1">
<div class="level-2">
</div>
</div>
<div class="level-1">
<div class="level-2">
</div>
</div>
</div>
Результат:
![enter image description here](https://i.stack.imgur.com/hN1E7.png)
Если вы хотите использовать TreeWalker вместо:
const frame = document.querySelector('#frame');
const domObserver = new MutationObserver(() => {
// If the container's innerHTML was assigned to, iterate over all descendants:
const treeWalker = document.createTreeWalker(frame);
const nodes = [];
let currentNode = treeWalker.currentNode;
while (currentNode) {
nodes.push(currentNode);
currentNode = treeWalker.nextNode();
}
console.log(nodes);
});
domObserver.observe(frame, {
childList: true,
subtree: true
})
// copy child nodes out of #template (as a string) and inject them into #frame for the observer to detect
document.querySelector('#frame').innerHTML = document.querySelector('#template').innerHTML
<div id="frame"></div>
<div id="template" style="display: none;">
<div class="level-1">
<div class="level-2">
<div id="nested">
I exist in the DOM but am not being seen by the MutationObserver
</div>
</div>
</div>
<div class="level-1">
<div class="level-2">
</div>
</div>
<div class="level-1">
<div class="level-2">
</div>
</div>
</div>