简体   繁体   中英

VueJS variable value does not update when not defined inside data object

I have a problem. When I did not define variable a in data of Vue instance, it does not update to match the new values.

<div id="app">
  <p>{{ a }}</p><br>
  <input type="text" v-model="a">
</div>

new Vue({
  el: "#app",
  data: {
  },
})

But when i use form in data, it works. Why is there such a difference?

<div id="app">
  <p>{{ form.a }}</p><br>
  <input type="text" v-model="form.a">
</div>

new Vue({
  el: "#app",
  data: {
    form:[]
  },
})

Also, in the case where I use both a and form , when I change input a , the text element is not updated. When i change input form.a , both text elements a and form.a are updated. Can someone please explain this behavior?

<div id="app">
  <p>{{ a }}</p><br>
  <input type="text" v-model="a">
  <p>{{ form.a }}</p><br>
  <input type="text" v-model="form.a">
</div>

new Vue({
  el: "#app",
  data: {
    form:[]
  },
})

My example : https://jsfiddle.net/0g8npdev/6/

The reason why a is not updated, is because it's not reactive.

Here's a good write up about reactivity in the vuejs docs: https://v2.vuejs.org/v2/guide/reactivity.html

It says:

Change Detection Caveats

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 .


Back to your question:

Let's have a look at how rendering is done in Vue.

First it defines getters and setters for all the properties in your data object (using defineProperty method). So every time you change the model (ie a or form ), the setter method is called and it will notify the watcher to render the change.

However, since you do not have the property a in your data object, vue doesn't define any setter for it. Hence when you update the input value, there is no way to inform the watcher about the change. (means, dom will not be updated).

Now, the same things happen for the form model too. But since you have defined that in your data object, vue will add the getter and setter methods for it. So when you update the input box with form model, it will notify the watcher to re-render the changes.

That's why a 's change is rendered only when form.a is changed :)

This is the most basic explanation I can do for this behavior. Hope it is clear. Feel free to ask if you have any doubts.

This post might help you: https://medium.com/@koheimikami/understanding-rendering-process-with-virtual-dom-in-vue-js-a6e602811782

If you wish to have 2-way data binding, you should declare the variable a in your Vue instance's data object.

<div id="app">
  <p>{{ a }}</p><br>
  <input type="text" v-model="a">
</div>
new Vue({
  el: "#app",
  data: {
    a: ''
  },
})

If you need the code then please refer to @iridescent 's answer.

Explanation of the behaviour:

Vue's core is Reactivity. As mentioned in the vue document it comes when you put JS object in data option.

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.

So first point to take is if you don't put a in data option it wont be reactive, and as you have put form in data option, hence making form.a as reactive(Vue will convert property 'a' to setter/getter).

Now why did only a get updated when you update the form.a in the jsfiddle link

Well as form is reactive, making form.a also reactive, so whenever any of the reactive property is updated, Vue updates the Virtual Dom which is then reflected in actual dom in the nextTick() . In simple terms, a is updated in memory but not reflected in dom because it's not reactive, but as form.a (reactive property) is updated virtualdom fetches the changes and updates them. So along with form.a the current value of a is also updated. And it is the intended behaviour the vue.

I would recommend you to read reactivity in depth docs here

I hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM