Mutation Observer 仅在父元素上触发
Mutation Observer only triggering on Parent Element
我正在尝试使用 MutationObserver 来监视应用程序库中已删除的节点,但似乎在删除(或替换)父元素时,它不会触发所有子元素的回调.
<button class="RemoveListButton">Remove List</button>
<div class="Container">
<ul class="ShoppingList">
<li class="Item">Pasta</li>
<li class="Item">Chips</li>
<li class="Item">Salsa</li>
</ul>
</div>
const removeWatcher = new MutationObserver(mutationList => {
const removedNodes = mutationList.flatMap(m => [...m.removedNodes])
console.log('Removing', removedNodes)
})
const container = document.querySelector('.Container')
removeWatcher.observe(container, { subtree: true, childList: true })
/* additional javascript to remove elements on click */
参见 JSFiddle https://jsfiddle.net/eq4ahsvc/3/
在示例中,当我删除单个列表项(通过单击它)时,我在控制台中看到该元素已被删除并被 Mutation Observer 看到。
但是,当我删除整个列表时,Mutation Observer 回调只会针对父元素触发,不会针对单个子元素触发。
有没有办法配置这种行为?理想情况下,每个元素都会触发 MutationObserver 回调,这样在删除列表时,我会看到删除列表的触发器,以及删除每个子元素的触发器。
子元素未从其父元素中删除,因此没有要观察的删除事件。参见:
const ul = document.querySelector('ul');
const li = ul.children[0];
ul.remove();
console.log(li.parentElement);
<button class="RemoveListButton">Remove List</button>
<div class="Container">
<ul class="ShoppingList">
<li class="Item">Pasta</li>
<li class="Item">Chips</li>
<li class="Item">Salsa</li>
</ul>
</div>
如您所见,<li>
仍然具有 .ShoppingList
的父元素,因为 .ShoppingList
已从其容器中删除,但单个 <li>
未从 .ShoppingList
.
中删除
如果您想查看每个已删除 <li>
的事件,除了删除 .ShoppingList
:
之外,您还必须迭代并显式删除它们
const removeWatcher = new MutationObserver(mutationList => {
const removedNodes = mutationList.flatMap(m => [...m.removedNodes])
console.log('Removing', removedNodes)
})
const container = document.querySelector('.Container')
removeWatcher.observe(container, { subtree: true, childList: true })
const button = document.querySelector('.RemoveListButton')
button.onclick = () => {
document.querySelectorAll('.ShoppingList > li').forEach(li => li.remove());
document.querySelector('.ShoppingList').remove()
}
const listItems = document.querySelectorAll('.Item')
listItems.forEach(item => item.onclick = () => {
event.target.remove()
})
<button class="RemoveListButton">Remove List</button>
<div class="Container">
<ul class="ShoppingList">
<li class="Item">Pasta</li>
<li class="Item">Chips</li>
<li class="Item">Salsa</li>
</ul>
</div>
对于你想要的,要么这样做,要么在观察者回调中递归地展平 removedNodes
数组中每个项目的所有子项。
我正在尝试使用 MutationObserver 来监视应用程序库中已删除的节点,但似乎在删除(或替换)父元素时,它不会触发所有子元素的回调.
<button class="RemoveListButton">Remove List</button>
<div class="Container">
<ul class="ShoppingList">
<li class="Item">Pasta</li>
<li class="Item">Chips</li>
<li class="Item">Salsa</li>
</ul>
</div>
const removeWatcher = new MutationObserver(mutationList => {
const removedNodes = mutationList.flatMap(m => [...m.removedNodes])
console.log('Removing', removedNodes)
})
const container = document.querySelector('.Container')
removeWatcher.observe(container, { subtree: true, childList: true })
/* additional javascript to remove elements on click */
参见 JSFiddle https://jsfiddle.net/eq4ahsvc/3/
在示例中,当我删除单个列表项(通过单击它)时,我在控制台中看到该元素已被删除并被 Mutation Observer 看到。
但是,当我删除整个列表时,Mutation Observer 回调只会针对父元素触发,不会针对单个子元素触发。
有没有办法配置这种行为?理想情况下,每个元素都会触发 MutationObserver 回调,这样在删除列表时,我会看到删除列表的触发器,以及删除每个子元素的触发器。
子元素未从其父元素中删除,因此没有要观察的删除事件。参见:
const ul = document.querySelector('ul');
const li = ul.children[0];
ul.remove();
console.log(li.parentElement);
<button class="RemoveListButton">Remove List</button>
<div class="Container">
<ul class="ShoppingList">
<li class="Item">Pasta</li>
<li class="Item">Chips</li>
<li class="Item">Salsa</li>
</ul>
</div>
如您所见,<li>
仍然具有 .ShoppingList
的父元素,因为 .ShoppingList
已从其容器中删除,但单个 <li>
未从 .ShoppingList
.
如果您想查看每个已删除 <li>
的事件,除了删除 .ShoppingList
:
const removeWatcher = new MutationObserver(mutationList => {
const removedNodes = mutationList.flatMap(m => [...m.removedNodes])
console.log('Removing', removedNodes)
})
const container = document.querySelector('.Container')
removeWatcher.observe(container, { subtree: true, childList: true })
const button = document.querySelector('.RemoveListButton')
button.onclick = () => {
document.querySelectorAll('.ShoppingList > li').forEach(li => li.remove());
document.querySelector('.ShoppingList').remove()
}
const listItems = document.querySelectorAll('.Item')
listItems.forEach(item => item.onclick = () => {
event.target.remove()
})
<button class="RemoveListButton">Remove List</button>
<div class="Container">
<ul class="ShoppingList">
<li class="Item">Pasta</li>
<li class="Item">Chips</li>
<li class="Item">Salsa</li>
</ul>
</div>
对于你想要的,要么这样做,要么在观察者回调中递归地展平 removedNodes
数组中每个项目的所有子项。