我有问题。当我未在Vue实例的数据中定义变量a
时,它不会更新以匹配新值。
<div id="app">
<p>{{ a }}</p><br>
<input type="text" v-model="a">
</div>
new Vue({
el: "#app",
data: {
},
})
但是当我在数据中使用form
时,它可以工作。为什么会有这样的区别?
<div id="app">
<p>{{ form.a }}</p><br>
<input type="text" v-model="form.a">
</div>
new Vue({
el: "#app",
data: {
form:[]
},
})
此外,在同时使用a
和form
的情况下,当我更改输入a
时,不会更新text元素。当我更改输入form.a
时,两个文本元素a
和form.a
都会更新。有人可以解释这种行为吗?
<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:[]
},
})
答案 0 :(得分:4)
a
未更新的原因是因为它没有反应。
在vuejs文档中,有关反应性的文章很好:https://vuejs.org/v2/guide/reactivity.html
它说:
更改检测警告
由于现代JavaScript的局限性(以及 Object.observe),Vue无法检测到属性的添加或删除。 由于Vue在 实例初始化, 属性必须存在于数据对象中 为了让Vue转换并使其具有反应性 。
回到您的问题:
让我们看看如何在Vue中完成渲染。
首先,它为数据对象中的所有属性定义getter和setter(使用defineProperty方法)。因此,每次更改模型(即a
或form
)时,都会调用setter方法,该方法将通知观察者以呈现更改。
但是,由于数据对象中没有属性a
,因此vue不会为其定义任何setter
。因此,当您更新输入值时,无法将更改通知给观察者。 (意味着,dom将不会更新)。
现在,form
模型也发生了同样的事情。但是由于您已经在数据对象中定义了它,所以vue将为其添加getter和setter方法。因此,当您使用form
模型更新输入框时,它将通知观察者重新呈现更改。
这就是为什么仅在更改a
时呈现form.a
的更改的原因:)
这是我可以为这种行为做的最基本的解释。希望清楚。随时询问您是否有任何疑问。
答案 1 :(得分:1)
如果希望进行双向数据绑定,则应在Vue实例的数据对象中声明变量a
。
<div id="app">
<p>{{ a }}</p><br>
<input type="text" v-model="a">
</div>
new Vue({
el: "#app",
data: {
a: ''
},
})
答案 2 :(得分:1)
如果您需要代码,请参考@iridescent的答案。
行为说明:
Vue的核心是反应性。如vue文档中所述,当您将JS对象放入data选项时会出现这种情况。
将纯JavaScript对象作为数据传递给Vue实例时 选项,Vue将遍历其所有属性并将其转换 使用Object.defineProperty获取/设置。
所以首先要考虑的是,如果您不将a
放在数据选项中,它将不会是被动的,并且因为您已经将form
放在数据选项中,因此使form.a
为react(Vue会将属性'a'
转换为setter / getter)。
现在,为什么在jsfiddle link中更新a
时仅更新form.a
由于form
是反应性的,因此form.a
也是反应性的,因此,无论何时更新任何反应性属性,Vue都会更新虚拟Dom,然后将其反映在{{1}中的实际dom中}。简而言之,nextTick()
在内存中被更新,但是由于它没有反应性而没有反映在dom中,但是随着a
(反应性属性)被更新,virtualdom会获取更改并进行更新。因此,与form.a
一起,form.a
的当前值也会被更新。这就是预期的行为。
我建议您阅读深度文档here中的反应性
希望对您有帮助。