vue.js - VueJS 观察属性和改变数据

标签 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;
  }
  }

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

检查 fiddle :https://jsfiddle.net/jj65t449/

最佳答案

您的值不收敛,因为您有一个不正确的函数

如果total=100perc=11,则val= 11:这是total * perc/100,好的。

如果total=100val=11,则perc= 11:这是total * val/100,好的。

如果perc=11val=11,则total= 100:这是 val/perc * 100不是您正在使用的 val * perc

由于您使用的是无效函数,总计将被设置为一个疯狂的值,这将触发 val 更新,这将再次触发 total 更新,将它们滚雪球般地变成无限个数(这是计算停止的时候,因为它们收敛了,如 infinity=infinity)。

因此,如果您更正您的函数,无限计算将停止。不是因为这些变量之间没有循环依赖(仍然存在!),而是因为它们将停止重新计算,因为值将停止变化(它们将收敛)。

请参阅下面的演示,我在其中修复了 v 观察器函数。 (请注意,我必须使用一些 Math.round() 以便它们在不更改输入数字的情况下收敛 - 删除它们以了解我的意思。这样做的缺点显然是四舍五入。 )

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);
    }
  }
})
<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>

修复函数后,如果不想要整数的选项

首先修复函数。现在,一些选项。

您可以只删除 Math.round()。不利之处在于,有时当您修改 v 时,循环最终会将 v 修改回来,修改量为 0.0000001。请参阅下面的演示。

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;
    }
  }
})
<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>

如果你不想要上面的内容,你将必须处理变量之间的循环依赖。

解决循环依赖。

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

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

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;
    }
  }
})
<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>

使用内部变量来保存值并使用“可设置”计算而不是观察者:

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; }
    }
  },
})
<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>

关于vue.js - VueJS 观察属性和改变数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49120930/

相关文章:

vuejs2 - 推杆没有定义! Laravel 5.4 与 Laravel Echo

vue.js - vue-cli3 公用文件夹 img 不显示

javascript - 计算属性内的Vue JS if/else语句

javascript - VueJS 中绑定(bind)函数的含义

javascript - 无法访问 Action vuex中的vue资源

javascript - 通过VueJS中的多个复选框将平面数组添加到v模型

vue.js - nuxt 在本地域上?

javascript - 我如何在 vue-router beforeEach 中使用 vuex Action

vue.js - 是否可以捕获我在 vuejs 中单击的元素属性?

vue.js - buefy Programmatic modal 从 child 的 parent 那里获取数据