0

In some component, I have this:

export default {
    data() {
        return {
            a: 'a',
            b: {}
        };
    }
}

Now, if I do this.a = 'aa'; somewhere, and I use this.a in a computed function, then everything happily updates reactively. If, however, I do this.b.key = 'bb'; ... then nothing happens. That is, this.b is not updated reactively, which makes us sad.

After some testing, it seems that I can trigger reactive updates to this.b, but only by assigning this.b = completelyNewObject; ... which is awkward.

Furthermore, in this case, this.b is not iterable, which makes using it in a computed function rather difficult.

So... what am I doing wrong here?

1

2 Answers 2

2

This is because b.key does not exist in the initial state of the data object, so Vue was not able to bind to it. The simple solution would be to add a key property to your initial object. You can also use Vue.set to assign the value.

new Vue({
  el: "#app",
  data(){
  	return {
      a: {},
      b: {
      	key: ''
      },
      c: {}
    }
  },
  methods: {
  	changeA(){
    	this.a.key = Math.random();
    },
    changeB(){
    	this.b.key = Math.random();
    },
    changeC(){
    	Vue.set(this.c, 'key', Math.random());
    }
  }
});
body {
  font-family: sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <p><button @click="changeA">Change me!</button> <strong>a.key:</strong> {{ a.key }}</p>
  <p><button @click="changeB">Change me!</button> <strong>b.key:</strong> {{ b.key }}</p>
  <p><button @click="changeC">Change me!</button> <strong>c.key:</strong> {{ c.key }}</p>
</div>

Notice how both b and c are reactive and update instantaneously, while a is not (it does update if you change b or c thanks to Vue re-rendering the app/component).

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for that. We are actually using nuxt, so Vue isn't a thing. Any idea how this would be done nuxtly?
I've never used Nuxt, but if you can't get access to the Vue object, your best bet would probably be to use method b above, and initialize the object with a key property already in it.
2

Well this is a limitation in Vue 2.x, and the possible solutions are using Vue.set or this.$set or Object.assign methods for example

this.$set(this.b, 'key', 'value to assign')

OR

Vue.set(this.b, 'key', 'value to assign')

OR

this.b= Object.assign({}, this.b, { key: 'value to assign' })

Note: this issue is already resolved in Vue 3 but mostly people are still on Vue 2x :)

3 Comments

Vue 3 is not released yet, only few RFC for Vue 2.x Next are available.
I've seen some projects using vue 3 already. I'll share link to that if I find it now
Yep, which is pretty much the solution I came up with (i.e., this.b = completelyNewObject;) but... any ideas about the other part of my question? this.b is not iterable. How to access the keys of this object, in a computed funciton?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.