需求
- 假定三数不大于n的整数v1,v2,v3,其和为n
- 要求改变任意数值,其它两数会自适应调整,确保三数和仍为n
- 调用规则 : 假定三数顺序固定索引为 0,1,2, 那么0数值增加了,则1数优先减少,不够则向2数借,即0->1->2->0->1->2…顺序
- 假定初始值分别为 40, 30, 30 , 定值和100,实现页面改变输入改变任意数,其它二数按规则自动变更
分析
- 父组件维护初始的数据信息数组及定值
- 被改变数值的组件向父组件发出事件时,携带当前改变的值,以及当前值所在的索引参数
- 父组件监听子组件事件回调内,可由定值减去其兄弟值得到当前索引上一次的旧值
- 比较新旧值,决定它的下一个数值是增是减
- 求模寻找循环次索引。如 当前索引值为index,三个数而言它的下一个·
ndex % 3
Dom
<body>
<div id="app">
<p>总数 {{items[0]}} + {{items[1] }} + {{items[2]}} = {{ total }}</p>
<li>value1:{{ items[0] }}</li>
<li>value2:{{ items[1] }}</li>
<li>value3:{{ items[2] }}</li>
<hr>
<h1>{{msg}}</h1>
<ol>
<li v-for="(value,index) in items">
<vinput v-model="value" :index="index" @input="calcu" />
</li>
</ol>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
代码
<script>
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>
`
})
var app = new Vue({
el: '#app',
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 = ""
},
}
})
console.log(Vue.version)
</script>