VueJs计算属性而不缓存

时间:2018-04-17 09:05:30

标签: vue.js vuejs2 vue-component

我有一个组件,它是一个输入字段,接受三种情况并将它们转换为内部状态(数字):

  • 输入:没有(空字符串);状态: undefined ;类:是空的;值:空字符串
  • 输入:任何正数;状态:正数;分类: ;值:正数
  • 输入: - ;州: -1 ;类:是未知的;价值: -
  • 否则:陈述: -2 ;类:无效;值:空字符串

此组件具有output计算属性,其中包含用于更改内部状态的setter以及在基于内部状态无效时返回数字,短划线或空字符串的getter。特殊情况是针对无效输入,我希望将该字段保留为空。

对于第一个无效字符,它运行良好,但是下一个字符会显示在字段中。我怀疑该值是缓存的,因为内部状态保持在invalid,因此使用了缓存。

<template>
  <input v-model="output" v-bind:class="state"/>
</template>

<script>
export default {
  name: 'TsResult',
  props: ['result'],
  data: function() {
    return {
      res: this.result
    }
  },
  computed: {
    state: function() {
      // ..
      if (this.res === -2) {
        return 'is-invalid'
      } else if (this.res === -1) {
        return 'is-unknown'
      }
      // ...
    },
    'output': {
      set: function(newVal) {
        //.. 
        if (isInvalid(newVal)) {
           this.res = -2;
        } else if (isUnknwon(newVal)) {
           this.res = -1;
        }
        // ...
      },
      get: function() {
        if (this.res === -2 ) { // Invalid
          return ''
        } else if (this.res === -1) { // Unknown
          return '-'
        } 
        // ...
      }
    }
</script>

使用方法而不是计算的getter是不适用的,因为我需要setter来执行验证。

使用观察者不是一个好主意,因为无效状态会更改输入值(通过设置空字符串)并重新触发接受空字符串的观察者。因此永远不会显示无效状态。

我可以在此计算属性上禁用缓存还是有更好的替代方法?

可能的hack是减少无效状态的内部状态,以便内部状态发生变化并重新计算值。但我想有一个更好的解决方案。

1 个答案:

答案 0 :(得分:2)

cache属性设置为false会禁用计算属性的缓存。有关详细信息,请参阅issue #1189 - Make computed property caching optionalrelevant commit

也许您可以覆盖接收实际按键的不可见输入字段,并将计算属性输出到较低的显示按钮?

如何在v-modelv-bind中分割v-on:input,就像大致一样(添加缺少的函数来测试它):

<template>
  <input v-bind:value="output_computed()" v-on:input="on_input($event.target.value)" v-bind:class="state"/>
</template>

<script>
function isValid(val) {
  return parseInt(val) != NaN && parseInt(val) >= 0;
}

function isInvalid(val) {
  return parseInt(val) == NaN || parseInt(val) < 0;
}

function isUnknown(val) {
  return !(isValid(val) || isInvalid(val));
}

export default {
  name: "TsResult",
  props: ["result"],
  data() {
    return {
      res: this.result,
      v: ""
    };
  },
  methods: {
    output_computed() {
      if (this.res === -2) {
        // Invalid
        return "";
      } else if (this.res === -1) {
        // Unknown
        return "-";
      } else if (this.res === -3) {
        return "";
      } else if (this.res === 0) {
        return this.v;
      }
    },
    on_input(newVal) {
      if (isInvalid(newVal)) {
        this.res = -2;
      } else if (isUnknown(newVal)) {
        this.res = -1;
      } else if (newVal === "") {
        this.res = -3;
      } else if (isValid(newVal)) {
        this.res = 0;
        this.v = newVal;
      }
      this.$emit("input", this.output_computed());
    }
  }
};
</script>

你可以看到它here on codesandbox.io