João
João

Reputation: 761

Vue cant watch object property setted inside for loop

I would like to set a object property inside a for-loop, and watch for those changes, but somehow Vue simply doesn't listen to all changes on the watch prop.

Here is my test code to simplify my issue (https://jsfiddle.net/hn2wepc9/).

If you click on the button, it should log 5 lines in the console (because of the loop method), but it only logs 1. I don't understand why Vue simply doesnt listen to all changes when I use Vue.set() inside a for loop and try to watch these changes.

<div id="app">
  <button @click="loop">Button</button>
</div>
new Vue({
  el: '#app',
  data: () => {
    return {
          obj: {
            name: 'John Doe'
        }
     }
  },
  methods: {
    loop() {
      for (let i = 0; i < 5; i++) {
        Vue.set(this.obj, 'name', 'Dohn Joe ' + i);
      }
    }
  },
  watch: {
    obj: {
      deep: true,
      handler(newVal, oldVal) {
        window.console.log(newVal.name + ' - ' + new Date().toLocaleString());
      }
    }
  }
});

Upvotes: 2

Views: 1190

Answers (1)

tony19
tony19

Reputation: 138256

By default, watchers are run asynchronously (in the next macro tick) as a performance optimization. I think the motivation is watchers are assumed to only care about the most recent change.

You can configure the watcher to be synchronous by setting the sync flag (one of several undocumented watch flags):

watch: {
  obj: {
    sync: true
  }
}

updated fiddle


For reference, in Vue 3, the flag is called flush with pre, post, and sync as possible values. See Effect flush timing.

Upvotes: 3

Related Questions