Mutation observer

The v-mutate directive utilizes the Mutation Observer API. It provides an easy to use interface for detecting when elements are updated.


Usage

v-mutate is a simple interface for the Mutation Observer APIthat is implemented with Vue directives. There are two main ways to alter v-mutate’s options; with directive modifiers using period notation, or with a custom options object. The following table contains information on the available directive modifiers:

ModifierDefaultDescription
.attrtrueThe attrmodifier monitors target node’s attribute changes
.chartrueThe charmodifier monitors changes to target node’s character data (and, its descendants if .sub is true)
.childtrueThe childmodifier monitors for the addition or removal of child nodes (and, its descendants if .sub is true)
.subtrueThe submodifier extends all monitoring to the entire subtree of target node
.onceundefinedThe once modifier invokes the user provided callback one time and disconnects the observer
.immediateundefinedThe immediate modifier invokes the user provided callback on mounted and does not effect .once

By default, v-mutate enables .attr, .char, .child, and .sub unless you manually apply one; in which case the undefined options are set to false:

Component.vue
<template>
  <div>
    <!-- attr, char, child, and sub are true -->
    <div v-mutate="..." />

    <!-- child is true, attr, char, and child are false -->
    <div v-mutate.child="...">
  </div>
</template>

In addition to the modifier syntax, the v-mutate directive is configurable via a custom object containing a handler and options key. The following example demonstrates how both processes achieve the same result:

Component.vue
<template>
  <div>
    <div v-mutate="{
      handler: onMutate,
        modifiers: {
          child: true,
          sub: true,
        }
      }"
    />

    <!-- is the same as -->

    <div v-mutate.child.sub="onMutate" />
  </div>
</template>

<script setup>
  function onMutate () {
    //
  }
</script>

Once

There may be times where your callback should only fire once. In these scenarios, use the once option to disconnect the observer after the first detected mutation. In the next example, we bind data value content to 2 separate v-cardcomponents and an input; then track the number of mutations that occur as we type:

Component.vue
<template>
  <div>
    <input type="text" v-model="content">

    <v-card v-mutate="onMutate">{{ content }}</v-card>

    <v-card v-mutate.once="onMutate">{{ content }}</v-card>
  </div>
</template>

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

  const content = shallowRef('Foo')
  const mutations = shallowRef(0)

  onMounted(() => {
    content.value = 'Bar'

    console.log(mutations.value) // 2

    setTimeout(() => {
      content.value = 'Foobar'

      console.log(mutations.value) // 3
    }, 200)
  })

  function onMutate () {
    mutations.value++
  }
</script>

When the value of content changes, both cards immediately call onMutate and iterate the value of the mutations data value. Because the second card is using the once modifier, it automatically unbinds its observer after the first change to content.

Immediate

Unlike the Intersection Observer API, the provided callback is not immediately invoked when a Mutation Observer is created. Vuetify normalizes this behavior with the immediate option. In the following example, the v-mutate directive invokes the onMutate method when the element is initially mounted in the DOM and with every mutation; based upon the provided options.

Component.vue
<template>
  <div v-mutate.immediate="onMutate">...</div>
</template>

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

  const mutations = shallowRef(0)

  onMounted(() => {
    console.log(mutations.value) // 1
  })

  function onMutate () {
    mutations.value++
  }
</script>

API

DirectiveDescription
v-mutateThe mutation observer directive

Examples

Ready for more?

Continue your learning with related content selected by the Team or move between pages by using the navigation links below.
Edit this page onGitHub