MutationObserver
可以通过配置 subtree: true
来监听目标节点及其所有子节点的变化。以下是具体实现方法及示例代码:
1. 基本用法:遍历所有节点
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
// 遍历新增的节点(包括子节点)
if (mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((node) => {
console.log('当前节点:', node);
// 递归遍历子节点(如果需要深度操作)
if (node.nodeType === Node.ELEMENT_NODE) {
const allChildren = node.querySelectorAll('*');
allChildren.forEach(child => {
console.log('子节点:', child);
});
}
});
}
});
});
// 配置:监听子节点变化(subtree: true)
observer.observe(document.body, {
childList: true, // 监听直接子节点变化
subtree: true // 监听所有后代节点变化
});
2. 关键参数说明
参数 | 作用 |
---|---|
childList: true |
监听目标节点的直接子节点增删。 |
subtree: true |
递归监听所有后代节点(包括深层嵌套的子节点)。 |
attributes: true |
监听属性变化(需结合 attributeFilter 过滤特定属性)。 |
3. 实际应用场景
场景1:动态加载的脚本拦截
observer.observe(document.head, {
childList: true,
subtree: true
});
// Mutation回调中检测动态插入的<script>
if (node.tagName === 'SCRIPT') {
console.log('拦截到脚本:', node.src);
}
场景2:监控DOM树的全量变化
// 打印所有新增的元素及其子元素
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
console.log('新增元素:', node.outerHTML);
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
4. 性能优化建议
- 限制监听范围:避免对
document
全量监听,改为特定容器(如document.getElementById('app')
)。 - 防抖处理:高频DOM操作时合并回调逻辑。
- 及时断开:不需要时调用
observer.disconnect()
。
5. 注意事项
- Shadow DOM:默认无法监听到 Shadow DOM内部的变化,需单独监听宿主元素。
- 文本节点:通过
node.nodeType === Node.TEXT_NODE
过滤文本变更。
通过合理配置 subtree: true
,可以高效地监控整个DOM树的动态变化。
内容由零声教学AI助手提供,问题来源于学员提问