ezegyfa
ezegyfa

Reputation: 25

VueJs run watcher handler immediatly after triggering

Example:

export default {
    data() {
        return {
            data1: 1,
            data2: 2
        }
    },
    mounted() {
        this.data1 = 2
        console.log(this.data2)
    },
    watch: {
        data1: {
            handler(newData1) {
                this.data2 = newData1 * 3
            }
        }
    }
}

Expected behavior: the browser write number 6 to the console

Current behavior: the browser write number 2 to the console

In this example I try to write the modified data2 after changed data1 value, but it write the data2 value before the watcher handler modify it. Is there a way to immediatly run watcher handler after triggering? I know I can use a computed property in this example but I need data in my project.

I tried to set the watcher immediatly property to true but isn't working.

Upvotes: 0

Views: 479

Answers (5)

Moritz Ringler
Moritz Ringler

Reputation: 15776

The watcher will not trigger in the middle of your mounted() handler, you need to wait until the handler has finished. This is how Javascript works, it is not a limitation in Vue.

Upvotes: 1

Estus Flask
Estus Flask

Reputation: 222309

As another answer explains, this is expected default behaviour and can be addressed by using nextTick, most times it's not the case because a computed is used instead, as suggested in yet another answer.

In Vue 3, this can be changed by the use of flush option:

mounted() {
    this.data1 = 2
    console.log(this.data2) // 6
},
watch: {
    data1: {
        handler(newData1) {
            this.data2 = newData1 * 3
        },
        flush: 'sync'
    }
}

Upvotes: 0

Kaushal Modi
Kaushal Modi

Reputation: 31

You can use computed property for data2

export default {
            data() {
                return {
                    data1: 1
                }
            },
            mounted() {
                this.data1 = 2
                console.log(this.data2)
            },
            computed: {
              data2() {
                return this.data1 * 3 
              }
            }
         }

Upvotes: 1

nart
nart

Reputation: 1848

Current behavior: the browser write number 2 to the console

It becauses Vue performs DOM updates asynchronously first run into mounted you made change to data1 (also puts console.log(this.data2) to callback queue at this point of time this.data2 = 2 thats why you see log 2) it also triggers watch of data1 If you log data2 here you see value of 6.

In order to wait until Vue.js has finished updating the DOM after a data change, you can use Vue.nextTick(callback) immediately after the data is changed

mounted() {
  this.data1 = 2
  this.$nextTick(() => {
     console.log(this.data2); // 6
  })
}

or use Vue.$watch - Watch an expression or a computed function on the Vue instance for changes

data() {
  return {
    data1: 1,
    data2: 2
  }
},
watch: {
  data1: function(val) {
    this.data2 = val * 3
  }
},
mounted() {
  this.data1 = 2
  this.$watch('data2', (newVal) => {
    console.log(newVal) // 6
  })
}

Upvotes: 0

Stephen Keating
Stephen Keating

Reputation: 1

I am not sure what the purpose of your code, but below will work

  mounted() {
    this.data1 = 2
    this.$nextTick(() => {
      console.log(this.data2)
    })
  },

Upvotes: 0

Related Questions