2017-06-20 65 views
0

我有一个复选框组件,用于跟踪用户是否已将某个项目保存为收藏夹。这些信息作为道具传入。具有道具和计算属性的V模型

因为我们不能/不应该改变从父组件传入的道具,所以我在计算属性上使用v-model。

<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> 

父组件控制将请求发送到收藏夹中的API &更新每个实体的状态,如果/当所述请求是成功的。

<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> 

但是,如果请求失败,是否可以防止首先检查复选框? this.favoritethis.checked都保持同步,但复选框的状态不是。

由于数据&道具保持正确,我也无法弄清楚如何触发重新渲染复选框以使其恢复到正确的状态。

+0

注意:虽然您传递它,但您的组件不接受“实体”作为道具。设置复选框的值应该是在检测到请求失败时适当地设置“entity.favorite”的问题。 –

+0

问题中的错字,而不是实际的组件中。我很抱歉。 'entity.favorite'永远是正确的。它起始于'entity.favorite = false'。即使计算出的prop' checked'和prop' favorite'(从entity.favorite传入)不会改变,复选框会被选中,我无法重置它。 – ebbishop

回答

1

我怀疑问题是favorite永不改变,所以Vue没有看到需要更新。在收到检查值(因此状态一致)后,应将其更新为true,然后在请求失败时再次将其更新为false

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>

你已经设置为适合于在最近重新.sync modifier,这将简化你的HTML有点方式:

<input-favorite :favorite.sync="entity.favorite"></input-favorite> 

然后你toggleFavorite做掉而是添加watch

watch: { 
    'entity.favorite': function (newValue) { 
    console.log("Updated", newValue); 
    if (newValue) { 
     setTimeout(() => { 
     console.log("Failed"); 
     this.entity.favorite = false; 
     }, 250); 
    } 
    } 
}