【发布时间】:2019-09-06 17:10:17
【问题描述】:
在我的根 Vue 实例中,我有一个包含一些数据的对象数组,我用它来渲染一组组件。这些组件对提供给它们的数据对象有一个观察者,它应该在每次更新对象时进行异步调用。
问题是,当我更新数组中某个对象的属性时,不会调用观察者。它不应该落入 Vue 的任何警告中,因为 a)我没有添加新属性,只是更新现有属性,并且 b)我没有以任何方式改变数组本身。那么为什么会这样呢?我该如何解决?
我的主要 Vue 实例:
let content = new Vue({
el: '#content',
data: {
testData: [
{ name: 'test1', params: {
testParam: 1
} },
{ name: 'test2', params: {
testParam: 1
} },
{ name: 'test3', params: {
testParam: 1
} }
]
}
});
我用来渲染组件的代码:
<div id="content">
<div v-for="item in testData">
<test-component v-bind="item"></test-component>
</div>
</div>
还有我的组件:
Vue.component('test-component', {
props: {
name: {
type: String,
required: true
},
params: {
type: Object,
required: true
}
},
data: function() {
return { asyncResult: 0 };
},
watch: {
params: function(newParams, oldParams) {
// I use a custom function to compare objects, but that's not the issue since it isn't even being called.
console.log(newParams);
if(!this.compareObjs(newParams, oldParams)) {
// My async call, which mutates asyncResult
}
}
},
template: `
<span>{{ asyncResult }}</span>
`
});
我的目标是改变给定对象的params 属性并触发观察者重新渲染相应的组件,但是当我尝试直接改变它时它不起作用。
示例(以及我希望组件的工作方式):
content.testData[2].params.testParam = 5;
不幸的是,它没有。使用Vue.set 也不起作用:
Vue.set(content.testData[2].params, 'testParam', 5);
我发现唯一有效的方法是完全分配一个新对象(这不是我每次必须改变属性时都想做的事情):
content.testData[2].params = Object.assign({}, content.testData[2].params, { testParam: 5 });
我也尝试过使用深度观察器,正如在类似问题中所建议的那样,但在我的情况下它不起作用。当我使用深度观察器时,会调用函数 ,但 newParams 和 oldParams 始终是同一个对象,无论我为我的属性设置哪个值。
是否有解决方案允许我仅通过设置属性来改变数组项?这将是最理想的结果。
【问题讨论】:
-
请参阅 Vue 文档中的 Common gotchas,其中解释了为什么会发生这种情况以及如何避免它。如果你考虑一下,Vue 不可能知道数组中对象的属性,这太复杂了。每次都创建一个新对象将是非常简单的解决方案,尽管不是最有效的。
标签: vue.js