-1

Consider below code:

let myData = {
    a: 1
}

const app = new Vue({
    data: myData
});

As Vue docs says when we try to add a property like below, the new property isn't reactive:

myData.b = 12;
console.log(app.b); // undefined

Vue docs suggests using Vue.set:

Vue.set(myData, 'b', 12);
console.log(app.b); // still undefined

Vue docs says Vue.set adds a property to a reactive object!

But I want to add b to the data's root level. I don't know how to make b reactive.

AliN11
  • 2,387
  • 1
  • 25
  • 40

3 Answers3

3

The docs clearly say you cannot add top level keys.

Vue does not allow dynamically adding new root-level reactive properties to an already created instance.

You must add a key to the root level object so you can update it later.

You can either:

  • create a key with a default value that you'll update. This means that you know the key before hand
  • create an empty object with a generic key (for instance dynamicProps) and use Vue.set to add dynamic keys at runtime to it.
tony19
  • 125,647
  • 18
  • 229
  • 307
Radu Diță
  • 13,476
  • 2
  • 30
  • 34
1

The question is simple: How to create a root level property and make it reactive?

The properties in data are only reactive if they existed when the instance was created. That means if you add a new property, like:

myData.b = 12;

Then changes to b will not trigger any view updates. If you know you'll need a property later, but it starts out empty or non-existent, you'll need to set some initial value. For example:

let myData = { a: 1, b: 0 }
// or,
let myData = { a: 1, b: null }

Now you can see changes to b are showing in the UI also:

let myData = { a: 1, b: 0 }
const app = new Vue({
  el: "#myApp",
  data: myData
})

myData.b = 12;
console.log(app.$data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <pre>{{ b }} </pre>
</div>
palaѕн
  • 72,112
  • 17
  • 116
  • 136
  • Thanks. I knew this works and it's a good alternative. But I wanted to know if it is possible to add a dynamic root-level property which name is unknown. Apparently it's not possible. – AliN11 Apr 22 '20 at 15:03
0

I can't find in documentation if you can add property to the root level and make it also reactive, but there is alternative solution.

let myData = {
    obj: {
     a: 1
    }
}

const app = new Vue({
    data: myData,
    watch: {
      obj: {
        handler(val) {
          console.log('watching !', val)
        },
        deep: true
      }
    }
});

Vue.set(app.obj, 'b', 12)

console.log(app.$data)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
Józef Podlecki
  • 10,453
  • 5
  • 24
  • 50
  • Thanks but you are adding a property to a nested object. As a result it is reactive just by using `Vue.set(app.obj, 'b', 12)` . No watcher needed. – AliN11 Apr 22 '20 at 14:56