Vue cant watch object property setted inside for loop

Viewed 510

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());
      }
    }
  }
});
1 Answers

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.

Related