I am seeing some weird behaviour here that was unexpected, but it makes intuitive-sense to me in terms of pure JavaScript.
I have a form controller that accumulates a this.thing
object that is sent to the server on the final submit. It's a multi-step form, so each step adds some data to this.thing
.
So the controller has:
data() {
return {
thing: {},
};
},
The DOM markup for this controller has a child like:
<a-child
:initial-thing="thing"
></a-child>
The child uses that prop to display its initial state, so it receives the prop and sets it into its own local state as instance data:
initialThing: {
type: Object,
required: true,
},
...
data() {
return {
thing: this.initialThing,
};
},
Then this child has a checkbox that is like this:
<a-checkbox
v-model="thing.field"
:initial-value="initialThing.field"
></a-checkbox>
This all works fine, except I just noticed that when the checkbox changes, it's mutating the parent controllers thing.field
value.
I'm making this question because I don't understand how Vue can do that, and the only thing that makes sense to me is that when the child does thing: this.initialThing
, it's allowing the child to call the setter function on that field on this.initialThing
.
It stops mutating the parent's state if I do this instead:
data() {
return {
thing: { ...this.initialThing },
};
},
In my actual app, it's more complex because there are 2 intermediate components, so the grandchild is mutating the grandparent's state, and it stems from the pattern I am describing here.
Can anyone provide a kind of textbook answer for what is happening here? I'm hesitant to rely on this behaviour because the code driving it is not explicit. It makes some of my $emit()
events redundant in favour of using this indirect/non-explicit way of sending data upstream.
Also to be clear, this has nothing to do with v-model
because it also does it if I do this.thing.field = 'new value';
. I believe it has everything to do with inheriting the getters/setters on this.initialThing
. Is it safe to rely on this behaviour? If I rely on it, it will make my code more concise, but a naive individual may have a hard time understanding how data is making it into the grandparent component.