【前端基础复盘】MutationObserverInit 参数分析

【前端基础复盘】MutationObserverInit 参数分析

【前端基础复盘】MutationObserver 接口的基本使用'

在上文中,复盘了 MutationObserver 接口的基本使用,接下来继续重温一下 MutationObserver 的一些进阶特性。

MutationObserverInit 对象参数分析

MutationObserver 实例化后 需要使用 observe() 方法来关联指定的节点和配置相关的监听参数。

其中第一个必传参数是 DOM节点,第二个必传参数则是 MutationObserverInit 对象。

javascript 复制代码
let observer = new MutationObserver((MutationRecord) => {
  console.log(MutationRecord.map((item) => item.target))
})
let childB = document.createElement('span')
document.body.append(childA)
observer.observe(childA, { attributes: true })

在上面的代码中,创建了 MutationObserver 实例并使用 observe 方法关联 ==childA==节点,并在 MutationObserverInit 中配置监听 attributes (DOM节点属性)的变化。

那么除了 attributes 我们还可以配置什么呢?MutationObserverInit对象提供了7个配置属性,下面就来过一遍 MutationObserverInit 的配置属性。

属性 说明
subtree boolean,表示除了目标节点,是否观察目标节点的字数(后代)。如果是false,则只观察目标节点的变化;如果是 true,则观察目标节点及其整个子树的变化。默认为 false。
attributes boolean,表示要观察目标节点的属性变化。默认 false
attributeFilter string[],表示要观察哪些属性的变化,默认观察所有属性
attributeOldValue boolean,表示MutationRecord 是否记录变化之前的属性值,默认为 false
characterData boolean, 表示修改字符数据是否触发变化事件,默认false
characterDataOldValue boolean, 类似于attributeOldValue 表示Mutation是否记录变化之前的字符数据,默认 false
childList boolean,表示修改目标节点的子节点是否触发变化事件,默认为 false
  • subtree 开启后可以观察子树

  • attributes 是一个常用的属性,一般监听节点属性(dataset、class、style等属性)变化时设置attributes为 true。

  • attributeFilter 如果监听的节点属性目标明确,就设置它,可以减少性能消耗。

  • attributeOldValue,类似于 vue中watch的oldValue,如果需要做变化对比的话,开启它。

  • 监听比较大的节点时不建议开启 subtree。

  • characterData 监听 节点内容或节点文本(TextNode)的变动 示例如下

vue 复制代码
<template>
  <div id="container">{{ name }}</div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue'

let name = ref('小明')
onMounted(() => {
  let observer = new MutationObserver((MutationRecord) => {
    console.log('characterData change', MutationRecord)
  })
  observer.observe(document.querySelector('#container').firstChild, {
    characterData: true,
  })
  setTimeout(() => {
    nextTick(() => {
      document.querySelector('#container').firstChild.nodeValue = 'hello world'
    })
  }, 1000)
})
</script>

观察属性

观察一个节点的属性,使用 attributes:true 可以像下面的写法

javascript 复制代码
let observer = new MutationObserver((MutationRecord) => {
  console.log('attributes change', MutationRecord)
})
observer.observe(document.body, {
  attributes: true,
})
// 添加属性
document.body.setAttribute('id', '1234')
// 修改属性
document.body.setAttribute('id', '5678')
// 移除属性
document.body.removeAttribute('id')

以上变化都会被监听到

attributes: true 时默认观察所有的属性并且不会记录原来的值。

如果指向观察某个或某几个属性可以使用attributeFilter 来设置白名单。

如果想记录改变前的值可以将attributeOldValue 设置为true。

javascript 复制代码
let observer = new MutationObserver((MutationRecords) => {
  console.log('attributes change', MutationRecords)
  console.log(MutationRecords.map((x) => x.oldValue)) // 打印id每次变化的值
})
observer.observe(document.body, {
  attributes: true,
  attributeFilter: ['id'], // 设置观察属性的白名单
  attributeOldValue: true, // 记录改变前的数据
})
// 添加属性
document.body.setAttribute('id', '1234')
// 修改属性
document.body.setAttribute('id', '5678')
// 修改属性
document.body.setAttribute('id', '91011')
// 移除属性
document.body.removeAttribute('id')

document.body.setAttribute('class', 'container') // 不会被观察

观察字符数据

MutationObserver 不仅可以观察节点的 attribute 的增删改同时也可以观察文本节点(Text、Comment或ProcessingInstruction 节点)的变化。

在实际操作中使用 innerHMTL 和 innerText 观察不到,因为要使用 textContent 或者 nodeValue。

设置元素文本内容的标准方式是 textContent 属性。Element 类也定义了 innerText 属性,与 textContent 类似。

但 innerText 的定义不严谨,浏览器间的实现也存在兼容性问题,因此不建议再使用了。

vue 复制代码
<template>
  <div id="container">123</div>
</template>

<script setup>
import { onMounted } from 'vue'
onMounted(() => {
  let dom = document.querySelector('#container')
  let observer = new MutationObserver((MutationRecords) => {
    console.log('characterData changed', MutationRecords)
    console.log(MutationRecords.map((x) => x.oldValue)) // 打印文本每次变化的值
  })
  observer.observe(dom.firstChild, {
    characterData: true,
    subtree: true,
    characterDataOldValue: true,
  })
  // 修改文本
  dom.firstChild.textContent = 'Hello World'
  // 修改文本
  dom.firstChild.textContent = 'Hello World2'
  // 修改文本
  dom.firstChild.textContent = 'Hello World3'
  // 修改文本
  dom.firstChild.textContent = '666'
})
</script>

观察子节点

MutationObserver 同时可以观察目标节点的子节点的添加和移除。

javascript 复制代码
onMounted(() => {
  let dom = document.querySelector('#container')
  let observer = new MutationObserver((MutationRecords) => {
    console.log('childList changed', MutationRecords)
  })
  observer.observe(dom, {
    childList: true,
  })
  // 添加属性
  const domH1 = document.createElement('h1')
  const domH2 = document.createElement('h2')
  const domH3 = document.createElement('h3')
  dom.append(domH1)
  dom.append(domH2)
  dom.append(domH3)
  dom.removeChild(domH3)
})

总结

  1. 观察节点属性
    1. attributes 开启观察
    2. attributeFilter 设置白名单指定要观察的属性
    3. attributeOldValue 保留历史记录
  2. 观察节点字符数据
    1. characterData 开启观察文本节点
    2. characterDataOldValue 保留历史记录
  3. 观察节点的子节点
    1. childList 观察目标节点子节点的变化
  4. 观察子树
    1. subtree 开启观察目标节点包括子节点(深度)
相关推荐
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-1 小时前
验证码机制
前端·后端
燃先生._.2 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖3 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235243 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240254 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar4 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人5 小时前
前端知识补充—CSS
前端·css
GISer_Jing5 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试