在V模型中,Vue计算的setter不会被触发

时间:2017-08-29 09:10:00

标签: javascript vuejs2 vue-router computed-properties computed-observable

我有一个值字符串管道,我想修改它。字符串管道的范围是0-5,所以我做了以下内容:

E7:H
new Vue({
  el: '#app',
  data: {
    valuesString: ""
  },
  computed: {
    values: {
      get() {
      	var values = this.valuesString ? this.valuesString.split("-") : [];
        if(values.length < 5)
        	values.push(null);
        return values;
      },
      set(values) {
        this.valuesString = values.filter(value => value).join("-")
      }
    }
  }
});

现在的问题是,我的计算<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script> <div id="app"> <div v-for="(value, i) in values" :key="i"> <select v-model="values[i]" style="width: 200px"> <option></option> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select> </div> <br> <span>valuesString: {{ valuesString }}</span> <br> <span>values: {{ values }}</span> </div>属性的setter没有被调用。

我的usecase是一个类似过滤器的过滤器。我从路由器获取values参数。用户应该能够选择1-5个类别进行过滤。每次过滤器更改时,路由器参数都应该更改,并且应该出现一个新的空选择,直到设置了5个类别。

2 个答案:

答案 0 :(得分:1)

我不完全确定我理解你在寻找什么,但我认为这样做会有所帮助:

  • 解析管道字符串并将其放入数组中
    • 请参阅unhaped计算属性
  • 循环遍历数组并将值放在选择框中
    • 循环应该出现在。结果绑定到valuesString
  • 应将所选值推送到结果数组,并清除选择框。
    • 请参阅pushValues方法。

Jfiddle example

<div id="app">
 <div>
   <select v-model="valuesString" @change="pushValues" style="width: 200px">
    <option v-for="p in unpiped">{{p}}</option>
    </select>
  </div>
<br>
  <span>valuesString: {{ valuesString }}</span>
<br>
  <span>unpiped: {{ unpiped }}</span>
 <br>
   <span>results: {{ results }}</span>
</div>

JS:

new Vue({
el: '#app',
 data: {
  valuesString: "",
  piped: "1|2|3|4|5",
  results: []
 },
 computed: {
  unpiped(){
    var v = this.piped.split("|");
    return v;
 },
},
 methods: {
   pushValues: function(){
    this.results.push(this.valuesString)
    this.valuesString = ""
 }
}
});

答案 1 :(得分:0)

麻省理,我的问题并不清楚。 Bert's comment is right

我通过解决方法解决了我的问题,但我并不那么满意。 maby任何人都可以帮我优化它。为此,我尝试使用计算机设置器。

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    values: [],
    valuesString: "",
    allValues: [...Array(5).keys()]
  },
  watch: {
    values (val) {
      if(val.toString() != this.filteredValues.toString()  && val.toString() != this.filteredValues.concat([null]).toString())
        this.$set(this, 'values', this.filteredValues);
      else if (this.valuesString != this.filteredValues.join('-'))
        this.$set(this, 'valuesString', this.filteredValues.join('-'));
    },
    valuesString (valuesString) {
      this.$set(this, 'values', valuesString.split('-'));
    }
  },
  computed: {
    filteredValues () {
      return this.values.filter(v => v);
    },
    modelArray () {
      let size = this.filteredValues.length;
      if(size < 5)
        size++;
      return new Array(size);
    }
  }
});
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
  <div v-for="(value, i) in modelArray" :key="i">
    <select v-model="values[i]" style="width: 200px">
      <option></option>
      <option v-for="(v, j) in allValues" :key="j" v-if="v == values[i] || filteredValues.indexOf(v.toString()) === -1">{{ v }}</option>
    </select>
  </div>
  <br>
  <span>valuesString: <input v-model="valuesString" /></span>
  <br>
  <span>values: {{ values }}</span>
  <br>
  <span>filteredValues: {{ filteredValues }}</span>
</div>
&#13;
&#13;
&#13;