Although vue.js provides us with useful computed data, we still need to use Watch in some scenarios.

By default, watch only executes when the value of the property being listened on changes.

Such as:

export default {
  data: (a)= > ({
    dog: ""
  }),
  watch: {
    dog(newVal, oldVal) {
      console.log(`Dog changed: ${newVal}`); }}};Copy the code

As shown in the code above, the dog function in Watch is executed only when the value of dog changes.

watch options

immediate

However, in some cases, you may need to run the listener immediately after creating the component. Sure, you could migrate the logic to Methods and then call it from the Watch and Created hook functions, but is there an easier way?

You can use the immediate: true option with Watch so that it executes immediately when the component is created.

export default {
  data: (a)= > ({
    dog: ""
  }),
  watch: {
    dog: {
      handler(newVal, oldVal) {
        console.log(`Dog changed: ${newVal}`);
      },
      immediate: true}}};Copy the code

deep

Watch also has a property called deep. The default value is false, which indicates whether to enable deep listening. Such as:

export default {
  data: (a)= > ({
    obj: {
      hello: 'james'}}),watch: {
    obj: {
      handler(newVal, oldVal) {
        console.log(`obj changed: ${newVal}`);
      },
      immediate: true.deep: true}}};Copy the code

Deep is a deep look in which listeners layer through, adding listeners to all attributes (and child attributes) of the object. This undoubtedly has a significant performance overhead, as modifying any property in OBj triggers the handler function in the listener.

If you only want to listen for a property in OBj, you can use string listening.

export default {
  data: (a)= > ({
    obj: {
      hello: 'james'}}),watch: {
    'obj.hello': {
      handler(newVal, oldVal) {
        console.log(`obj changed: ${newVal}`);
      },
      immediate: true.deep: false}}};Copy the code

Dynamically addwatch

Vue source code $watch implementation:

Vue.prototype.$watch = function (expOrFn, cb, options) {
  var vm = this;
  if (isPlainObject(cb)) {
    return createWatcher(vm, expOrFn, cb, options)
  }
  options = options || {};
  options.user = true;
  var watcher = new Watcher(vm, expOrFn, cb, options);
  if (options.immediate) {
    try {
      cb.call(vm, watcher.value);
    } catch (error) {
      handleError(error, vm, ("callback for immediate watcher \"" + (watcher.expression) + "\" ")); }}return function unwatchFn () { watcher.teardown(); }};Copy the code

Based on this, we can modify the sample code above to dynamically add watch, for example:

export default {
  data: (a)= > ({
    obj: {
      hello: 'james'
    }
  }),
  mounted(){
    this.$watch('obj.hello'.this.handler, {
      immediate: true.deep: false})},methods: {
    handler(newVal, oldVal) {
      console.log(`obj changed: ${newVal}`); }}};Copy the code

Warning:

In normal cases, it is not recommended$watchTo dynamically addwatchBecause you also need to manually log out of the Watch listening event

The cancellationwatch

If you want to add watch dynamically, you need to log out manually. If this.$watch is called, there is a return value. If this.$watch is called, there is a return value.

Modify the code as follows:

let unWatch = null
export default {
  data: (a)= > ({
    obj: {
      hello: 'james'
    }
  }),
  mounted(){
    unWatch = this.$watch('obj.hello'.this.handler, {
      immediate: true.deep: false})},methods: {
    handler(newVal, oldVal) {
      console.log(`obj changed: ${newVal}`);
    }
  },
  beforeMount(){
    unWatch()
    unWatch = null}};Copy the code