数据处理的问题

<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的值不变....
像这样的规律, 有什么比较好的方式实现....

阅读 1.8k
2 个回答

体验地址
页面可查看源码,主要逻辑如下:

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组件实现的主要代码完整实现地址点击

  1. 求模寻找循环次索引。如 当前索引值为index,三个数而言它的下一个 index % 3
  2. 自定义的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>
        `
    })
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏