0
votes

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}]}]
    }
}
1

1 Answers

1
votes

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>