When reading "Reactivity in Depth" in the documentation, I see two points which I am not sure how to interpret:
When you pass a plain JavaScript object to a Vue instance as its data option, Vue will walk through all of its properties and convert them to getter/setters using
Object.defineProperty
(...)
Due to the limitations of modern JavaScript (and the abandonment of
Object.observe
), Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.
How does this related to nested object such as
[
{
"a": 1,
"b": [
{
"c": 1
},
...
]
},
{
"a": 10,
"b": [
{
"c": 10
},
...
]
},
...
]
Specifically, how should such object be presented to data()
so that it is reactive?
data() {
return {
likeThis: [],
orLikeThat: [{}],
orMoreDetailed: [{a: null, b:[]}],
orTheFullStucture: [{a: null, b:[{c: null}]}]
}
}
I think that you are misunderstanding the property addition/deletion caveat. The statement in the first section of the docs that you reference holds true for your example object. If you set that object as a property of the object returned by the data
method, everything within that object will be reactive.
Here's a simple example where I've set your object as myNestedData
in the data
method. I've bound myNestedData[0].b[0].c
via v-model
to an input element and you can see that changes to that value are reflected in the myNestedData
object itself.
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data() {
return {
myNestedData: [{
"a": 1,
"b": [{
"c": 1
}]
}, {
"a": 10,
"b": [{
"c": 10
}]
}]
};
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="myNestedData[0].b[0].c" type="number">
<br>
{{ myNestedData }}
</div>
Any of the examples you gave in your final section of code would be fully reactive, as in my example above. The property addition/deletion caveat only comes into play if you attempt to add or remove properties from those reactive data objects.
Here's a simple example where a foo
property is initially set in the data
method with a value of [{ a: 'apple' }]
. Then this.foo[0].b
is set to 'banana'
in the created
hook of the component. But, because the b
property of this.foo[0]
didn't exist before, that property is not reactive. You can see this by changing the value of the second input, which is bound to via v-model
to foo[0].b
. Changing that value does not update the value that property in foo
.
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data() {
return {
foo: [{ a: 'apple' }]
};
},
created() {
this.foo[0].b = 'banana';
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="foo[0].a">
<input v-model="foo[0].b">
<br>
{{ foo }}
</div>