假设我有三个字段:
当百分比或总数发生变化时,值应该发生变化。当值改变时,总数应该改变。
因此,我为这些属性创建了一些观察者:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
目前观察者相互触发,这可能是它无法正常工作的原因。
检查小提琴:https : //jsfiddle.net/jj65t449/
您的值不会收敛,因为您的函数不正确。
如果total= 100, perc= 11,则val= 11:也就是total * perc/100,好的。
如果total= 100, val= 11,则perc= 11:也就是total * val/100,好的。
如果perc= 11,val= 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);
}
}
})Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
首先修复函数。现在,一些选择。
您只需删除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;
}
}
})Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
如果您不想要上述内容,则必须处理变量之间的循环依赖。
这是 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;
}
}
})Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
使用内部变量来保存值并使用“可设置”计算而不是观察者:
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; }
}
},
})Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3498 次 |
| 最近记录: |