【问题标题】:V-model with props & computed properties具有道具和计算属性的 V 模型
【发布时间】:2017-11-23 08:17:07
【问题描述】:

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

因为我们不能/不应该改变从父组件传入的 props,所以我在计算属性上使用 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 都保持同步,但复选框的状态不同步。

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

【问题讨论】:

  • 注意:您的组件不接受 entity 作为道具,尽管您正在传递它。设置复选框值应该只是在检测到请求失败时适当设置entity.favorite 的问题。
  • 问题中的错字,而不是实际组件中的错字。我很抱歉。 entity.favorite 总是正确的。它以entity.favorite = false 开头。即使计算出的道具checked 和道具favorite(从entity.favorite 传入)没有改变,复选框被选中并且我无法重置它。

标签: vue.js vuejs2


【解决方案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);
    }
  }
}

【讨论】:

    猜你喜欢
    • 2017-04-16
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 2020-04-20
    • 2020-10-25
    • 2015-11-28
    相关资源
    最近更新 更多