我有一个只计算日期格式的计算属性:
computed: {
items() {
return this.licenseItems.map(function(license) {
license.expires_at = moment(license.expires_at).format('MM/DD/YYYY');
return license;
});
}
}
我将licenseItems
传递给带有.sync
修饰符的表单组件,并从表单中发出update:field
事件。在vue dev工具中,我可以看到licenseItems
(数据)已正确更新,但items
(已计算)仍显示旧数据,因此未执行重新计算。
我注意到如果我删除地图并从计算属性中返回licenseItems对象,则会更新它。使用同步修饰符时,Vue在映射对象上的计算属性是否存在问题?
答案 0 :(得分:2)
您应该知道您正在修改计算中的基础对象。从你的小提琴:
computed: {
mapped: function() {
return this.items.map(function(item) {
let original = item.date;
item.date = moment(item.date).format('MM/DD/YYYY');
console.log(original + ' => ' + item.date);
return item;
});
}
}
您的incrementDates
函数也会直接修改基础对象。
由于items
的每个元素都是一个对象,item
是对同一个对象的引用,因此您的例程会更新items
本身的成员。如果您打算修改对象值,则应使用watch
而不是computed
。如果您想要一个不修改数据项的正确计算,则需要deep copy个对象。
在下面的示例中,您可以看到数据值和计算值是不同的,但计算结果基于数据。此外,update
事件与sync
一起使用以更新父级中的值,而不是直接在组件中更新的值。您可以输入Date
了解的任何日期格式来设置值。
new Vue({
el: '#app',
data: {
licenseItems: [{
expires_at: Date.now()
}]
},
computed: {
items() {
return this.licenseItems.map(function(license) {
const newItem = Vue.util.extend({}, license);
newItem.expires_at = moment(license.expires_at).format('MM/DD/YYYY');
return newItem;
});
}
},
components: {
myUpdater: {
props: ['items'],
methods: {
doUpdate(event, index) {
const newObj = this.items.map(item => Vue.util.extend({}, item));
newObj[index].expires_at = new Date(event.target.value);
console.log("new object", newObj);
this.$emit('update:items', newObj);
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<my-updater :items.sync="licenseItems" inline-template>
<div>
<input v-for="item, index in items" :value="item.expires_at" @change="doUpdate($event, index)">
</div>
</my-updater>
<div v-for="item in items">
{{item.expires_at}}
</div>
</div>