Vue 2 Reactivity

Reactivity in Vue.js is accomplished through getters and setters as defined in the Object.defineProperty method. Let’s make a watered down version of what’s happening in Vue.

Object.defineProperty(obj, key, {

enumerable: true,

configurable: true,

get:function(){

return value;

},

set:function(newValue){

if(value !== newValue){

value = newValue;

tellTheWorldIhaveChanged(); //somebody is watching!

}

}

});

Using this type of setup, every time we make a change to the property, it notifies watchers and dependencies that need to know that there has been a change. This property setup is what happens on initialization of our model and when we explicitly call Vue.set/vm.$set.

With this setup, however, the following requires extra help:

Array updates by index

data(){

return {

names:[]

}

}

...

this.persons[0] = 'John Elway';

You are probably aware that this will not trigger an update. In fact, the holy guide of Vue explicitly mentions caveats to arrays. Why is this so? Because setters on arrays have no means of detecting assignments by index.

One option to handle this is to use Vue.set

Vue.set(this.names, 0, 'John Elway');

However, Vue is kind enough to wrap a few array methods for us, so we can update our arrays using those array methods.

this.names.push('John Elway');

2. Adding properties dynamically

data(){

return {

names:[]

}

} ... this.$data.lastAddedName = 'John Elway';

Not the best example, right? I probably should have already knew that this property would exist, but there are cases that we might not know the property name. JavaScript loosed-typedness allows us to add properties with ease. Vue reactivity, however, has no clue that we added this property.

Here I come to save the day! — Vue.set

Vue.set(this.$data,'lastAddedName','John Elway');

If only we had a way to avoid all this Vue.set usage and give ourselves back the array indexes.

Vue 3 Reactivity

Welcome to the world of reactivity through proxies. Proxies are a feature introduced in ES6 AKA ES2015 AKA they’ve been out for a while. Because of that, I’m sure you have learned about them, but may have not been able to use them in a production environment because they’re unshimmable. No polyfill and no way to fake them in older browsers.

Fortunately, the syntax is not absurd. In fact, it’s somewhat familiar.

let data = {

names:[]

}; data.names = new Proxy(data.names,{

set:function(obj, prop, value){

if(obj[prop] !== value){

obj[prop] = value;

tellTheWorldIhaveChanged();

}

}

});

Not only will this proxy catch the indexed array placement we mentioned earlier, but it will also fire when the array methods are called. No wrappers needed.

What about adding properties dynamically?

data = new Proxy(data,{

set:function(obj, prop, value){

if(obj[prop] !== value){

obj[prop] = value;

tellTheWorldIhaveChanged();

}

}

}); data.lastAddedName = 'John Elway'; //tellTheWorldIhaveChanged()