在下面的代码片段中,我有两个Vue组件,每个组件都有一个包含两个对象的items
数组。如果该对象的items
属性是真实的,则每个组件的模板都设置为显示show
数组的对象。数组中的第一个对象最初的show
值为true
。第二个对象没有设置show
值。
new Vue({
el: '#ex1',
data: () => ({ items: [{name: 'apple', show: true}, {name: 'banana'}] }),
mounted() {
// 2nd item's show property setting is not detected here
this.items[1].show = true;
}
})
new Vue({
el: '#ex2',
data: () => ({ items: [{name: 'apple', show: true}, {name: 'banana'}] }),
mounted() {
// 2nd item's show property setting IS detected...
this.items[1].show = true;
// ...when the 1st item's show property is set to false
this.items[0].show = false;
}
})

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="ex1">
Example 1:
<div v-if="items[0].show">{{ items[0] }}</div>
<div v-if="items[1].show">{{ items[1] }}</div>
</div>
<div id="ex2">
Example 2:
<div v-if="items[0].show">{{ items[0] }}</div>
<div v-if="items[1].show">{{ items[1] }}</div>
</div>
&#13;
在第一个示例中,我将show
数组中第二个对象的items
属性设置为true
。 Vue没有检测到模板中的变化,这是预期的。
在第二个示例中,我将第二个对象的show
属性设置为true
,然后将第一个对象的show
属性设置为false
。在这种情况下,Vue 会检测items
数组的两个元素的更改并相应地更新模板。鉴于Vue的Change Detection Caveats,我不希望出现这种情况。
这似乎是一个非常无害的错误(如果它甚至可以作为一个错误),所以我不确定它是否值得报告。但是,我想知道是否有人能够解释这种行为。为什么Vue在第二个示例中检测到对象添加了show
属性?
答案 0 :(得分:4)
更改被动属性(第一个对象的show
)会触发重新渲染。 Vue忠实地呈现模板引用的对象的当前状态,其中包括第二个对象。
第二个对象的show属性仍然没有被动,对它的更改不会更新Vue。它只是对触发更新的第一个对象上的被动属性状态的更改。
换句话说,更改第二个对象的show属性,因为它是在事后添加的,将永远不会更新Vue,但更改第一个对象上的show属性将始终更新,并且更新将只渲染数组的当前状态,无论它是如何添加的。
我不会认为这是一个错误。
一种简单的方法是在更新后将数组记录到控制台。您将看到第二个对象的show属性未被观察到,但仍然存在。
修改强> 我想根据评论稍微澄清一下。第二个对象的更改出现在Vue中的原因是因为整个Vue被重新渲染而第二个对象直接在Vue中被引用。例如,如果您将值传递给组件,则不会重新呈现第二个对象。
这是一个示例,显示当值传递给组件时,第二个对象永远不会更新(因为组件管理渲染)。
console.clear()
Vue.component("item", {
props: ["item"],
template: `
<div>Item Show: {{item.show}}</div>
`
})
new Vue({
el: '#ex2',
data: () => ({ items: [{name: 'apple', show: true}, {name: 'banana'}] }),
mounted() {
// 2nd item's show property setting IS detected...
this.items[1].show = true;
// ...when the 1st item's show property is set to false
this.items[0].show = false;
}
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="ex2">
This will show false, because that is the current state and this object's show
property is reactive
<item :item="items[0]"></item>
<hr>
This will not show *anything*, despite the current state of show=true
because the object's show property is not reactive
<item :item="items[1]"></item>
</div>
&#13;
答案 1 :(得分:-1)
如您发布的链接中所述:
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the
Vue.set(对象,键,值)
解决而不是 this.items [1] .show = true 你可以写:
Vue.set(this.items[1], 'show', true)
希望它清楚