V型带道具&计算属性

时间:2017-06-20 16:53:13

标签: vue.js vuejs2

我有一个复选框组件,用于跟踪用户是否已将项目保存为收藏夹。此信息作为道具传递。

因为我们不能/不应该改变从父组件传入的道具,所以我在计算属性上使用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&amp;发送请求。如果/当请求成功时更新每个实体的状态。

<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都保持同步,但复选框的状态不会同步。

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

1 个答案:

答案 0 :(得分:2)

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

&#13;
&#13;
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");
      }
    }
  }
});
&#13;
<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>
&#13;
&#13;
&#13;

你设置它的方式适用于最近重新引入的.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);
    }
  }
}