crsdahl
crsdahl

Reputation: 595

Watching for array additions/deletions in Vue

When watching an array in Vue like this:

watch: {
  myarray(val) {
    // react to additions or deletions on myarray
  },
},

and adding or removing items on that array like this:

this.myarray.splice(this.myarray.findIndex((d) => d.id === myId), 1);
this.myarray.push({name: 'New Item'});

how do I watch for these additions or deletions on the array. Two ways I could do this:

But both methods would add a performance overhead to my application (There are up to a hundred thousand elements in this array).
Is there any way the watch callback can pass me a list of additions or deletions.

The (value, mutation) callback described here: https://optimizely.github.io/vuejs.org/api/instance-methods.html would be exactly what I need. Unfortunately that doesn't seem to work anymore.

Upvotes: 4

Views: 931

Answers (1)

crsdahl
crsdahl

Reputation: 595

The best method I came up with so far would be overwriting the push and splice methods of the array. I don't really like this solution though, as it doesn't use Vue's built-in reactivity which does basically the same I am doing here:

created() {
  this.myarray.push = (...args) => {
    //do something with args
    return Array.prototype.push.apply(this.myarray, args);
  };
  this.myarray.splice = (...args) => {
    //do something with args
    return Array.prototype.splice.apply(this.myarray, args);
  };
  //any more array methods you want to intercept
},

Alternatively, and if you don't need existing code using push() and splice() to be compatible with this, you could of course define new functions such as push2() and splice2() to avoid overwriting the native functions.

Or you could define such functions on the component itself to act as setter for the array.

Note that when using the above snippet you loose Vues own reactivity on that array. To keep both you would have to do:

created() {
  const originalPush = this.myarray.push;
  const originalSplice = this.myarray.splice;
  this.myarray.push = (...args) => {
    //do something with args
    return originalPush.apply(this.myarray, args);
  };
  this.myarray.splice = (...args) => {
    //do something with args
    return originalSplice.apply(this.myarray, args);
  };
  //any more array methods you want to intercept
},

Upvotes: 2

Related Questions