Vue3 Watch Properties

In this chapter, we will introduce Vue3 watch propertieswatch, we can usewatchto respond to data changes.

watchIt is used to monitor changes in reactive properties and execute specific operations when properties change. It is a reactive mechanism in Vue that allows you to respond accordingly when data changes and execute custom logic.

watchIt provides more control and flexibility when reactive properties change, allowing your components to better respond to data changes and execute corresponding logic.

The following example implements a counter using watch:

Example

<div id = "app">
    <p style = "font-size:25px;">Counter: {{ counter }}</p>
    <button @click = "counter++" style = "font-size:25px;">Click Me</button>
</div>
   
<script>
const app = {
  data() {
    return {
      counter: 1
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('counter', function(nval, oval) {
    alert('Counter value change:' + oval + ' changed to ' + nval + '!');
});
</script>

Try it Yourself »

The following example performskilometersandRiceconversion between:

Example

<div id = "app">
Kilometers: <input type = "text" v-model = "kilometers"  @focus="currentlyActiveField = 'kilometers'">
Rice: <input type = "text" v-model = "meters" @focus="currentlyActiveField = 'meters'">
</div>
<p id="info"></p>    
<script>
const app = {
  data() {
    return {
      kilometers : 0,
      meters:0
    }
  },
  watch : {
    kilometers:function(newValue, oldValue) {
      // Check if it is the current input field
      if (this.currentlyActiveField === 'kilometers') {
        this.meters = newValue * 1000
      }
    },
    meters : function (newValue, oldValue) {
      // Check if it is the current input field
      if (this.currentlyActiveField === 'meters') {
        this.kilometers = newValue/ 1000;
      }
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('kilometers', function (newValue, oldValue) {
  // This callback will be called after vm.kilometers changes
  document.getElementById ("info").innerHTML = "Value before change: " + oldValue + ", value after change: " + newValue;
})
</script>

Try it Yourself »

Click the "Try it Yourself" button to view the online example.

In the above code, we created two input fields. In the data property, the initial values of kilometers and meters are both 0. The watch object creates two monitoring methods for the data object: kilometers and meters.

When we input data into the input field, watch will monitor data changes in real time and change its own value. You can watch the video demonstration below:

Using watch in Async Loading

For loading async data, Vue provides a more general method through the watch option to respond to data changes.

The following example uses the axios library, which will be introduced in detail later.

Example

<!--Because the ecosystem of AJAX libraries and general-purpose tools is already quite rich, Vue's core code does not duplicate-->
<!--these features in order to stay lightweight. This also allows you to freely choose the tools you are more familiar with.-->
<script src="https://cdn.staticfile.org/axios/0.27.2/axios.min.js"></script>
<script src="https://cdn.staticfile.org/vue/3.2.37/vue.global.min.js"></script>
<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        question: '',
        answer: 'Each question needs to end with a ? mark.'
      }
    },
    watch: {
      // Whenever the question changes, this function will run, requiring the question to end with a ? mark, compatible with both Chinese and English ?
      question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1 || newQuestion.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getAnswer() {
        this.answer = 'Loading...'
        axios
          .get('/try/ajax/json_vuetest.php')
          .then(response => {
            this.answer = response.data.answer
          })
          .catch(error => {
            this.answer = 'Error! Unable to access the API. ' + error
          })
      }
    }
  }).mount('#watch-example')
</script>

Try it Yourself »

Usage Summary

watch is a reactive data watching mechanism provided by Vue 3, which can watch single or multiple properties.

You can handle data changes by passing a callback function, with support for options such as deep watching and immediate execution.

1. Basic Usage

In Vue 3, the watch function is used to watch reactive properties.

When the watched property value changes, Vue will trigger the callback function to execute.

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count, // The property being watched
      (newVal, oldVal) => { // The callback function when it changes
        console.log(`count changed from ${oldVal} to ${newVal}`);
      }
    );

    return {
      state
    };
  }
};

2. Watching Multiple Reactive Properties

If you want to watch multiple reactive properties at the same time, you can pass an array containing the properties to watch:

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    });

    watch(
      [() => state.count, () => state.name], // Watching multiple properties
      ([newCount, newName], [oldCount, oldName]) => {
        console.log(`count changed from ${oldCount} to ${newCount}`);
        console.log(`name changed from ${oldName} to ${newName}`);
      }
    );

    return {
      state
    };
  }
};

3. Deep Watching

If what you want to watch is an object or array, and you want to watch its nested properties, you can use thedeep: trueoption. This will watch all property changes of the object.

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      user: {
        name: 'Alice',
        age: 25
      }
    });

    watch(
      () => state.user, // Watch the entire object
      (newVal, oldVal) => {
        console.log('User object changed:', newVal, oldVal);
      },
      { deep: true } // Enable deep watching
    );

    return {
      state
    };
  }
};

4. Immediate Execution

By default, watch only triggers the callback when the watched value changes. If you want the callback to execute immediately when the component loads, you can setimmediate: true。

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count, // Watch property
      (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
      },
      { immediate: true } // Immediate execution
    );

    return {
      state
    };
  }
};

5. Async Operations

If you need to perform async operations in watch, you can directly use async and await in the callback function, which allows you to handle operations such as API requests, data storage, etc.

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count,
      async (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
        // Assume an async request is made
        await fetch(`https://api.example.com/count/${newVal}`);
      }
    );

    return {
      state
    };
  }
};

6. Watching Multiple Properties and Using the handler Function

You can also use watch as a handler for watching multiple properties, like this:

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    });

    const handler = ([newCount, newName], [oldCount, oldName]) => {
      console.log(`count changed: ${oldCount} → ${newCount}`);
      console.log(`name changed: ${oldName} → ${newName}`);
    };

    watch([() => state.count, () => state.name], handler);

    return {
      state
    };
  }
};

7. watchEffect - Simplified Watching

Vue 3 also provides the watchEffect API, which is more concise than watch. It can automatically track changes in reactive data without needing to specify a specific data source.

Example

import { reactive, watchEffect } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watchEffect(() => {
      console.log(`count is: ${state.count}`);
    });

    return {
      state
    };
  }
};

watchEffect will automatically detectstate.countchanges and trigger the callback when changes occur.

8. The flush Option

The flush option is used to control the execution timing of watch callbacks.

By default, watch callbacks execute after the DOM is updated. If you need to execute the callback before the update, you can useflush: 'pre'。

Example

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count,
      (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
      },
      { flush: 'pre' } // Execute the callback before the update
    );

    return {
      state
    };
  }
};
Other Extensions