V 模型与道具 &计算属性 [英] V-model with props & computed properties
问题描述
我有一个复选框组件,用于跟踪用户是否已将项目保存为收藏.此信息作为道具传递.
因为我们不能/不应该改变从父组件传入的 props,所以我在计算属性上使用 v-model.
<input class="favorite" type="checkbox" v-model="checked"></模板><脚本>模块.出口 = {道具:['收藏'],计算:{检查:{获取:函数 getChecked() {返回 this.favorite;},设置:函数 setChecked(newVal) {this.$emit('update:favorite', newVal);}}}};
父组件控制发送请求到收藏夹api &如果/当请求成功时更新每个实体的状态.
<输入收藏夹@update:favorite="toggleFavorite":favorite="entity.favorite"></input-favorite></模板><脚本>模块.出口 = {方法: {切换收藏夹:功能切换收藏夹(val){如果(瓦尔){this.$store.dispatch('postFavorite', { id: this.entity.id, name: this.entity.name });} 别的 {this.$store.dispatch('deleteFavorite', this.entity.id);}}}};
但是,如果请求失败,是否可以首先阻止复选框被选中?this.favorite
和 this.checked
都保持同步,但复选框的状态不同步.
因为数据&props 保持正确,我也无法弄清楚如何触发重新渲染复选框以使其恢复到正确状态.
我怀疑问题在于 favorite
永远不会改变,所以 Vue 认为不需要更新.您应该在收到检查值后将其更新为 true
(因此状态一致),然后在请求失败时再次将其更新为 false
.
Vue.component('inputFavorite', {模板:'#input-favorite',道具:['收藏'],计算:{检查:{获取:函数 getChecked() {返回 this.favorite;},设置:函数 setChecked(newVal) {this.$emit('update:favorite', newVal);}}}});新的 Vue({el: '#app',数据: {实体: {最喜欢的:假的}},方法: {切换收藏夹:功能切换收藏夹(val){如果(瓦尔){console.log("发布");this.entity.favorite = true;//模拟失败setTimeout(() => {console.log("失败");this.entity.favorite = false;}, 250);} 别的 {console.log("删除");}}}});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script><模板 id="input-favorite"><input class="favorite" type="checkbox" v-model="checked"></模板><div id="应用程序"><input-favorite @update:favorite="toggleFavorite" :favorite="entity.favorite"></input-favorite>
您的设置方式适用于最近重新引入的.sync
修饰符,这会稍微简化你的 HTML:
<input-favorite :favorite.sync="entity.favorite"></input-favorite>
然后你去掉toggleFavorite
,而是添加一个watch
:
观看:{'entity.favorite': 函数 (newValue) {console.log("更新", newValue);如果(新值){setTimeout(() => {console.log("失败");this.entity.favorite = false;}, 250);}}}
I have a checkbox component that tracks whether or not an item has been saved by the user as a favorite. This information is passed in as a prop.
Because we can't/shouldn't mutate props passed in from a parent component, I am using v-model on a computed property.
<template>
<input class="favorite" type="checkbox" v-model="checked">
</template>
<script>
module.exports = {
props: ['favorite'],
computed: {
checked: {
get: function getChecked() {
return this.favorite;
},
set: function setChecked(newVal) {
this.$emit('update:favorite', newVal);
}
}
}
};
</script>
The parent component controls sending requests to the favorites api & updating the state of each entity if/when the request is successful.
<template>
<input-favorite
@update:favorite="toggleFavorite"
:favorite="entity.favorite"
></input-favorite>
</template>
<script>
module.exports = {
methods: {
toggleFavorite: function toggleFavorite(val) {
if (val) {
this.$store.dispatch('postFavorite', { id: this.entity.id, name: this.entity.name });
} else {
this.$store.dispatch('deleteFavorite', this.entity.id);
}
}
}
};
</script>
If the request fails, however, is it possible to prevent the checkbox from getting checked in the first place? Both this.favorite
and this.checked
stay in sync, but the state of the checkbox does not.
Because the data & props stay correct, I'm also having trouble figuring out how I could trigger a re-render of the checkbox to get it back to the correct state.
I suspect the problem is that favorite
never changes, so Vue doesn't see a need to update. You should update it to true
upon receiving the checked value (so state is consistent) and then update it again to false
when the request fails.
Vue.component('inputFavorite', {
template: '#input-favorite',
props: ['favorite'],
computed: {
checked: {
get: function getChecked() {
return this.favorite;
},
set: function setChecked(newVal) {
this.$emit('update:favorite', newVal);
}
}
}
});
new Vue({
el: '#app',
data: {
entity: {
favorite: false
}
},
methods: {
toggleFavorite: function toggleFavorite(val) {
if (val) {
console.log("Post");
this.entity.favorite = true;
// Mock up a failure
setTimeout(() => {
console.log("Failed");
this.entity.favorite = false;
}, 250);
} else {
console.log("Delete");
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<template id="input-favorite">
<input class="favorite" type="checkbox" v-model="checked">
</template>
<div id="app">
<input-favorite @update:favorite="toggleFavorite" :favorite="entity.favorite"></input-favorite>
</div>
The way you have set this up lends itself to the recently-reintroduced .sync
modifier, which would simplify your HTML a bit:
<input-favorite :favorite.sync="entity.favorite"></input-favorite>
Then you do away with toggleFavorite
and instead add a watch
:
watch: {
'entity.favorite': function (newValue) {
console.log("Updated", newValue);
if (newValue) {
setTimeout(() => {
console.log("Failed");
this.entity.favorite = false;
}, 250);
}
}
}
这篇关于V 模型与道具 &计算属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!