2017-06-20 67 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); 
    } 
    } 
}