<Input v-model="value1" @on-blur="handleBlur('value1')" />
<Input v-model="value2" @on-blur="handleBlur('value2')" />
<Input v-model="value3" @on-blur="handleBlur('value3')" />
data(){
return {
value1 : 40,
value2 : 30,
value3 : 30,
}
}
3个input 框, 它们的初始值分别为 40, 30, 30 (不管怎么修改, 它们3个值加起来都是100);
现在想通过一个事件去修改: 比如修改value1, 把他原来的40 ,改成 30, 那么value2 会自动加上10,变成40, value3 的值不变,
如果修改成value1为50,因为value1,value2,value3相加(50+30+30)的值超出了100, 所以value2的值要自动减去10,变成20,即:value1等于50时,value2等于20,value3等于30,
如果value1修改成80时,value2则变成0,value3变成20,
同样的 如果修改value2的值,把原来的30 改成50时, value3优先减成0, 然后再减value1的值, 如果把value2原来的值改成20,则优先加value3的值变成40, value1的40 不变;
当修改value3的值时, 优先改变value1的值, 如果把value3的原来的60 改成50, 则value1的值为0,然后value2 的值变成40,如果把value3的值改成10,则value1 的值变成60,value2的值不变....
像这样的规律, 有什么比较好的方式实现....
体验地址
页面可查看源码,主要逻辑如下:
for (let i = 1; i < len; i++) {
if (diffValue === 0) { break; }
const j = (i + index) % len;
let currentItemValue = values[j].value;
console.log('====>', j, currentItemValue)
let preCalcNextValue = currentItemValue + diffValue;
if (preCalcNextValue > sum) {
diffValue -= sum - currentItemValue;
this.updateValuesArrAt(j, sum);
} else if (preCalcNextValue < 0) {
diffValue += currentItemValue;
this.updateValuesArrAt(j, 0);
} else {
diffValue = 0;
this.updateValuesArrAt(j, preCalcNextValue);
}
}
###
可借鉴react中的井字棋思路,即子组件接收父组件下发的prop,父组件负责算法的实现,状态变更维护,监听子组件事件。下面是用vue 2.6.11
自定义Vinput
组件实现的主要代码完整实现地址点击
- 求模寻找循环次索引。如 当前索引值为
index
,三个数而言它的下一个index % 3
- 自定义的
input
组件负责展示,其发出事件由父组件监听,将子状态改变计算好通知兄弟组件
<ol>
<li v-for="(value,index) in items">
<vinput v-model="value" :index="index" @input="calcu" />
</li>
</ol>
父组件
data: {
total: 100,
items: [40, 30, 30],
msg: ''
},
methods: {
calcu(newValue, index) {
if (!newValue) {
newValue = 0
} else {
newValue = parseInt(newValue)
}
if (isNaN(newValue) || (newValue < 0 || newValue > this.total)) {
this.msg = `请输入不大于${this.total}的正整数`
return
}
// 获取输入后的副本数据
let items = [...this.items].map(x => parseInt(x))
// 计算新旧值变动差额,以便计算下一个值是增或减
let diff = newValue - (this.total - items[(index + 1) % 3] - items[(index + 2) % 3])
if (diff > 0) {
if (diff > items[(index + 1) % 3]) {
items[(index + 1) % 3] = 0
} else {
items[(index + 1) % 3] = items[(index + 1) % 3] - diff
}
} else {
items[(index + 1) % 3] = items[(index + 1) % 3] - diff
}
items[index] = newValue
items[(index + 2) % 3] = this.total - items[index] - items[(index + 1) % 3]
this.items = items
this.msg = ""
},
}
vinput
子组件
// 组件数据流动方向 0->1->2->0...
Vue.component('vinput', {
model: {
prop: 'value',
event: 'input'
},
props: ['value', 'index'],
template: `
<p>
value{{index}}:
<input
type="text"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value,index)"
>
</p>
`
})