我有一个可以从数据库更新的对象列表。
因此,当我加载列表时,对象只有ID和名称。
当我单击一个对象时,我会加载其他任意长度的字段-这就是为什么我不使用列表中的对象加载它们的原因。
我发现更新对象时,保持反应性https://vuejs.org/v2/guide/reactivity.html可能很困难,因此我需要找到一些解决方法。
此代码几乎可以正常工作:
axios.get('/api/news', item.id).then(function(response){
if (response){
Object.assign(item, response.data.item);
}
});
但是问题在于,从一开始就没有出现过的字段不再具有100%的反应性。发生的事情是,仅当我更改另一个以前的字段时,新字段才进行反应性更新。因此,如果我显示具有旧属性和新属性的2个文本字段,则如果更改第二个属性,则在更改第一个属性之前,该字段将不会更新。
我从组件中获得了项目对象:
data () {
return {
items: [],
}
},
和
<div v-for="item in items" @click="selectItem(item)" >
<span>{{item.name}}</span>
</div>
然后将项目传递给函数selectItem。
加载新字段 并使它们保持反应性的正确模式是什么? (注意:我不能按字段分配字段-不管它是哪个对象,我都想重用相同的代码,所以我需要这样的解决方案来一次更新对象而不列出所有新字段。) / p>
注意。该代码在组件内部起作用。
答案 0 :(得分:2)
完全修订后的文章:好的,您给出的示例使用一个数组,该数组具有its own caveats,尤其是您不能直接设置vm.items[indexOfItem] = newValue
之类的值并使它起作用。
因此,您必须将Vue.set
与数组一起用作第一个参数,将索引用作第二个参数。这是一个向对象项目添加name
属性,然后使用Vue.set
将项目设置为Object.assign
创建的新对象的示例。
new Vue({
el: '#app',
data: {
items: [{
id: 1,
other: 'data'
}, {
id: 2,
other: 'thingy'
}]
},
methods: {
selectItem(parent, key) {
const newObj = Object.assign({}, parent[key], {
name: 'some new name'
});
Vue.set(parent, key, newObj);
setTimeout(() => {parent[key].name = 'Look, reactive!';}, 1500);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="item, index in items" @click="selectItem(items, index)">
<span>{{item.name || 'empty'}}</span>
</div>
<pre>
{{JSON.stringify(items, null, 2)}}
</pre>
</div>
答案 1 :(得分:1)
看看Change-Detection-Caveats,如果您使用“常规分配”方法,Vue将无法检测到属性的添加或删除。
您必须使用Vue.set(object, key, value)
尝试如下操作:
axios.get('/api/news', item.id).then(function(response){
if (response){
let item = {}
Vue.set(item, 'data', response.data.item)
}
});
将比item.data
重新激活。