VueJS正在观看属性和更改数据

时间:2018-03-05 23:04:22

标签: vue.js vuejs2

假设我有三个字段:

image

当百分比或总数发生变化时,值应该会发生变化。 当值发生变化时,总计应该会改变。

因此,我为这些属性创建了一些观察者:

watch:{
  p: function(nv,ov){
    this.v = this.t * nv / 100;
  },
  t: function(nv,ov){
     this.v = nv * this.p / 100;
  },
  v: function(nv,ov){
    this.t = nv * this.p;
  }
  }

目前,观察者互相触发,这可能是它无法正常工作的原因。

检查小提琴:https://jsfiddle.net/jj65t449/

1 个答案:

答案 0 :(得分:4)

您的值不会收敛,因为您的功能不正确

如果total = 100perc = 11,则val = 11total * perc/100,确定

如果total = 100val = 11,则perc = 11total * val/100,确定

如果perc = 11val = 11,则total = 100val / perc * 100,<当您使用时 val * perc

由于您使用的是无效功能,因此总计将设置为疯狂值,这将触发val更新,这将再次触发total更新,将其滚雪球化为无限数量(当计算停止时,因为它们会聚,因为infinity = infinity)。

因此,如果您更正了您的功能,无限计算将停止。并不是因为这些变量之间没有循环依赖(仍有!),但是因为它们会停止重新计算,因为值会停止变化(它们会收敛)。

请参阅下面的演示,其中我修复了v观察程序功能。 (请注意,我必须使用一些Math.round(),因此它们会在不改变输入数字的情况下收敛 - 删除它们以查看我的意思。显然,这个数字是舍入的。)

&#13;
&#13;
new Vue({
  el: "#app",
  data: {
    t: 100,
    p: 10,
    v: 10
  },
  watch: {
    p: function(nv, ov) {
      this.v = this.t * nv / 100;
    },
    t: function(nv, ov) {
      this.v = Math.round(nv * this.p / 100);
    },
    v: function(nv, ov) {
      this.t = Math.round(nv / this.p * 100);
    }
  }
})
&#13;
<script src="https://unpkg.com/vue"></script>
<div id="app">
  Total:<br/>
  <input type="number" v-model="t" />
  <hr/> Percent: <br/>
  <input type="number" v-model="p" />
  <hr/> Value:
  <br/>
  <input type="number" v-model="v" />
</div>
&#13;
&#13;
&#13;

修复功能后,选项如果您不想要圆号

首先修复该功能。现在,有些选择。

您可以删除Math.round()。缺点是,有时当您修改v时,周期将最终修改v,返回0.0000001。见下面的演示。

&#13;
&#13;
new Vue({
  el: "#app",
  data: {
    t: 100,
    p: 10,
    v: 10
  },
  watch: {
    p: function(nv, ov) {
      this.v = this.t * nv / 100;
    },
    t: function(nv, ov) {
      this.v = nv * this.p / 100;
    },
    v: function(nv, ov) {
      this.t = nv / this.p * 100;
    }
  }
})
&#13;
<script src="https://unpkg.com/vue"></script>
<div id="app">
  Total:<br/>
  <input type="number" v-model="t" />
  <hr/> Percent: <br/>
  <input type="number" v-model="p" />
  <hr/> Value:
  <br/>
  <input type="number" v-model="v" />
</div>
&#13;
&#13;
&#13;

如果你不想要上述内容,你将拥有来处理变量之间的循环依赖。

解决循环依赖关系。

这是Vue的常见问题。有一些选择,但它们看起来不漂亮。选择最适合你的。

观察者更改为方法并删除v-model

&#13;
&#13;
new Vue({
  el: "#app",
  data: {
    t: 100,
    p: 10,
    v: 10
  },
  methods: {
    updateP: function(newP) {
      this.p = newP;
      this.v = this.t * newP / 100;
    },
    updateT: function(newT) {
      this.t = newT;
      this.v = newT * this.p / 100;
    },
    updateV: function(newV) {
      this.v = newV;
      this.t = newV / this.p * 100;
    }
  }
})
&#13;
<script src="https://unpkg.com/vue"></script>

<div id="app">
  Total:<br/>
  <input type="number" :value="t" @input="updateT($event.target.value)" />
  <hr/> Percent: <br/>
  <input type="number" :value="p" @input="updateP($event.target.value)" />
  <hr/> Value:
  <br/>
  <input type="number" :value="v" @input="updateV($event.target.value)" />
</div>
&#13;
&#13;
&#13;

使用内部变量来保存值并使用&#34; settable&#34;计算而不是观察者:

&#13;
&#13;
new Vue({
  el: "#app",
  data: {
    tVal: 100,
    pVal: 10,
    vVal: 10
  },
  computed: {
    p: {
      get() { return this.pVal; },
      set(newP) { this.pVal = newP; this.vVal = this.tVal * newP / 100; }
    },
    t: {
      get() { return this.tVal; },
      set(newT) { this.tVal = newT; this.vVal = newT * this.pVal / 100; }
    },
    v: {
      get() { return this.vVal; },
      set(newV) { this.vVal = newV; this.tVal = newV / this.pVal * 100; }
    }
  },
})
&#13;
<script src="https://unpkg.com/vue"></script>
<div id="app">
  Total:<br/>
  <input type="number" v-model="t" />
  <hr/> Percent: <br/>
  <input type="number" v-model="p" />
  <hr/> Value:
  <br/>
  <input type="number" v-model="v" />
</div>
&#13;
&#13;
&#13;