Skip to main content

Overview

MutationObserver composable for detecting DOM changes. Wraps the MutationObserver API with lifecycle management.

Features

  • MutationObserver API wrapper
  • Pause/resume/stop functionality
  • Automatic cleanup on unmount
  • SSR-safe (checks SUPPORTS_MUTATION_OBSERVER)
  • Hydration-aware
  • Configurable observation options

Function Signature

function useMutationObserver(
  target: MaybeElementRef,
  callback: (entries: MutationObserverRecord[]) => void,
  options?: UseMutationObserverOptions
): UseMutationObserverReturn

Parameters

target
MaybeElementRef
The element to observe.
callback
(entries: MutationObserverRecord[]) => void
The callback to execute when a mutation is observed.
options
UseMutationObserverOptions
immediate
boolean
default:"false"
Call the callback immediately with synthetic data.
once
boolean
default:"false"
Stop observing after first mutation.
childList
boolean
default:"true"
Observe additions and removals of child nodes.
attributes
boolean
default:"false"
Observe changes to attributes.
characterData
boolean
default:"false"
Observe changes to character data.
subtree
boolean
default:"false"
Observe mutations in descendants.
attributeOldValue
boolean
default:"false"
Record the previous value of changed attributes.
characterDataOldValue
boolean
default:"false"
Record the previous value of changed character data.
attributeFilter
string[]
Array of attribute names to observe.

Return Value

isActive
Readonly<Ref<boolean>>
Whether the observer is currently active.
isPaused
Readonly<Ref<boolean>>
Whether the observer is currently paused.
pause
() => void
Pause observation.
resume
() => void
Resume observation.
stop
() => void
Stop observation and clean up.

Examples

Observe child list changes

import { ref } from 'vue'
import { useMutationObserver } from '@vuetify/v0'

const container = ref<HTMLElement>()

useMutationObserver(
  container,
  (mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === 'childList') {
        console.log('Added nodes:', mutation.addedNodes)
        console.log('Removed nodes:', mutation.removedNodes)
      }
    })
  },
  { childList: true }
)

Observe attribute changes

const element = ref<HTMLElement>()

useMutationObserver(
  element,
  (mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === 'attributes') {
        console.log('Attribute changed:', mutation.attributeName)
      }
    })
  },
  { 
    attributes: true,
    attributeOldValue: true 
  }
)

Observe specific attributes

useMutationObserver(
  element,
  (mutations) => {
    mutations.forEach((mutation) => {
      console.log(`${mutation.attributeName} changed`)
    })
  },
  { 
    attributes: true,
    attributeFilter: ['class', 'id', 'data-state'] 
  }
)

Observe entire subtree

const container = ref<HTMLElement>()

useMutationObserver(
  container,
  (mutations) => {
    console.log(`${mutations.length} mutations detected`)
  },
  { 
    childList: true,
    subtree: true 
  }
)

Pause and resume

const { pause, resume, isPaused } = useMutationObserver(
  container,
  handleMutations,
  { childList: true }
)

// Temporarily pause
pause()

// Resume observing
resume()

Once mode

useMutationObserver(
  element,
  (mutations) => {
    console.log('First mutation detected, stopping observer')
  },
  { 
    childList: true,
    once: true 
  }
)

Track DOM changes in a list

<script setup>
import { ref } from 'vue'
import { useMutationObserver } from '@vuetify/v0'

const listRef = ref<HTMLElement>()
const itemCount = ref(0)

useMutationObserver(
  listRef,
  (mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === 'childList') {
        itemCount.value = listRef.value?.children.length || 0
      }
    })
  },
  { childList: true }
)
</script>

<template>
  <div>
    <p>Items: {{ itemCount }}</p>
    <ul ref="listRef">
      <!-- List items -->
    </ul>
  </div>
</template>

Mutation Record Properties

type
'attributes' | 'childList' | 'characterData'
The type of mutation.
target
Node
The node affected by the mutation.
addedNodes
ObservableNodeList
Nodes added to the tree.
removedNodes
ObservableNodeList
Nodes removed from the tree.
previousSibling
Node | null
The previous sibling of added or removed nodes.
nextSibling
Node | null
The next sibling of added or removed nodes.
attributeName
string | null
The name of the changed attribute.
attributeNamespace
string | null
The namespace of the changed attribute.
oldValue
string | null
The previous value (requires attributeOldValue or characterDataOldValue).

Use Cases

  • Dynamic content tracking: Monitor when content is added or removed
  • Attribute monitoring: Track changes to class names, data attributes, etc.
  • DOM validation: Ensure DOM structure meets requirements
  • Performance monitoring: Detect excessive DOM mutations
  • Debug tools: Log DOM changes during development
  • Rich text editors: Track content changes in contentEditable elements

Notes

  • Automatically stops observing when once: true and a mutation occurs
  • Hydration-aware: defers setup until client-side hydration completes
  • SSR-safe: returns valid API with isActive: false when MutationObserver is not supported
  • immediate option provides synthetic data on first mount
  • Default observes childList only; explicitly enable other options as needed

Build docs developers (and LLMs) love