MutationObserver

MutationObserver

MutationObserver 用于观察 DOM 元素的变化。可以观察到在父节点中添加或删除子节点、属性值或数据内容等变化。在 MutationObserver 之前,DOM 更改事件由 Mutation 事件处理,比如 DOMAttrModified、DOMAttributeNameChanged 和 DOMNodeInserted。MutationObserver 被 DOM3 中定义的 Mutation 事件所替代。避免这些突变事件的实际原因是性能问题和跨浏览器支持。

基础使用

创建观察者

它可以通过调用它的构造函数和传递处理函数和配置选项来创建。我们有一个选项来指定我们想要跟踪或观察什么样的变化。

const config = { childList: true, attributes: true, characterData: true };
const observer = new MutationObserver(handler);
  • childList: true,表示观察与子节点相关的变化

  • attributes:true,表示观察属性更改

  • characterData; true,表示观察目标元素的数据内容的变化

{
attributes: true,
attributeOldValue: true,
characterData: true,
characterDataOldValue: true,
childList: true,
subtree: true,
}

定义要观察的目标对象

observer.observe(...) 方法接受应该被观察到的目标元素。

const parent = document.querySelector(.parent”);
observer.observe(parent, config);

定义回调事件

根据在观察者创建过程中使用的配置,当目标元素中发生更改时,会执行回调函数。回调函数是用突变记来对象触发的,该对象包含目标元素中发生的突变类型。

function handler(mutationRecords, observer) {
mutationRecords.forEach(mutationRecord => {
switch (mutationRecord.type) {
case 'childList':
break;
case 'attributes':
break;
default:
}
});
}
/* Create mutation observer */
const config = {
childList: true,
attributes: true,
characterData: true
};
const observer = new MutationObserver(handler);
/* Observe target */
const parent = document.querySelector('.parent');
observer.observe(parent, config);
/* Callback function when mutation happens */
function handler(mutationRecords, observer) {
console.log('Handle mutation');
mutationRecords.forEach(mutationRecord => {
const info = document.querySelector('.infoBoard');
switch (mutationRecord.type) {
case 'childList':
info.innerText =
'Mutation Observer handler: Child node added or removed';
break;
case 'attributes':
info.innerText = `Mutation Observer handler: Parent attribute modified: ${
mutationRecord.attributeName
} : ${mutationRecord.target.children.length}`;
break;
default:
info.innerText = '';
}
});
}
/* Add child nodes when clicked on add child node button */
document.querySelector('.addBtn').addEventListener('click', () => {
console.log('Add child');
const child = document.createElement('div');
child.className = 'child';
child.innerText = 'Child ';
parent.appendChild(child);
});
/* Remove child nodes when clicked on remove child node button */
document.querySelector('.removeBtn').addEventListener('click', () => {
console.log('Remove child');
const child = parent.firstChild;
parent.removeChild(child);
});
/* Change attribute value when clicked on change attribute button */
document.querySelector('.changeAttrBtn').addEventListener('click', () => {
console.log('Change attribute value');
parent.setAttribute('data-count', parent.childNodes.length);
});