TobiasLounsbury / EmpireSkillTest

0 stars 0 forks source link

Question: Use of this.$set #12

Open djfrailey opened 4 years ago

djfrailey commented 4 years ago

I noticed that you're using this.$set in a number of places and am curious as to why. My understanding is that this.$set should only be used if you need force reactivity on an object property where Vue would otherwise fail to do so through the normal means of this.bar = 'foo'; where bar has already been declared inside of the components data() method.

TobiasLounsbury commented 4 years ago

When I fetch the gataData it returns a complex object. calling this.gameData = response.data replaces the entire object. Vue only attaches watchers on object declaration. When I replace the entire object the watchers are wiped out. I use this.$set to induce Vue to rebuild the watchers and bind them to the front end.

djfrailey commented 4 years ago

Could you provide me with a link to the documentation that states Vue only attaches watchers on object declaration?

My understanding is this:

Adding properties to an already declared object results in the property not being reactive. Replacing an already declared object with a new object instance, will result in all properties on the newly referenced instance to be reactive. So this.gameData = response.data should result in all properties from response.data being declared reactive, since its object instance is different from the one already stored in this.gameData

https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

This can somewhat be illustrated by running this jsfiddle and checking the console output. You will see that all properties added via a new object instance have an associated get/set method, as will the property added using this.$set

The only one that does not, is added to an already existing object without the use of this.$set

image

Functioning under this belief the only time a call to this.$set should be necessary is when you need to add a property that isn't already declared on a reactive object.

TobiasLounsbury commented 4 years ago

Sorry, I was sitting in a hospital waiting room (waiting to pick up someone from a scheduled procedure) when I was answering this question when I got called back and probably should have opted to not hit comment and given a more fleshed out answer later. My rushed answer led to terminology that I suspect is getting us mixed up. The situation that I was attempting to solve by using this.$set is that the gameData object exists at the start of the game. but not all of the nodes within the squares array exist. Additionally even though squares is numerically indexed, the squares can be filled out of order, so javascript treats squares as an object rather than an array. The way they are populated is that the server records the move and sends back an update gameData object. Because not all of the nodes within squares exist yet, when calling this.gameData = response.data; the resulting gameData object has nodes within squares that are non-reactive, just as you described above. I do not have any documentation that says "only on object declaration" those were my own words to describe the behavior I saw during development. Perhaps a better way to re-phrase the behavior I observed would be to say it thusly: When replacing the whole gameData object without using this.$set I observed that the sub-object squares was non-reactive, even if the previous gameData object had a squares sub-object that was reactive. When the complete squares object was present at the first creation of gameData, such as when viewing a completed game that was a draw, the squares object was reactive, leading me to the phrasing that the reactivity was assigned on object declaration. My solution to the situation was to assign gameData via this.$set. I hope that clears up my what I was trying to describe and why I assigned the data this way. I would love to see other solutions to this type of situation if you have any insights to offer.