e.target和vue的冲突

303 阅读2分钟

e.target和v-model的冲突

问题发现

页面是实现input输入框检测用户输入的字符数(中文为2个字,英文为1个字)

// 页面部分(限制用户输入10个字符)
<template slot="remark" slot-scope="action, record">
          <a-input size="small" type="text"  v-model="record.remark" :disabled="pageType=='details'" @keyup="limitLength($event,10)" ></a-input>
</template>
​
​
//js部分
limitLength(e,maxLength) {
    const target=e.target
    const value = target.value
    const split = value.split('');
    const map = split.map((s, i) => {
        return (value.charCodeAt(i) >= 0 && value.charCodeAt(i) <= 128) ? 1 : 2;
    });
        let n = 0;
        const charLength = map.length > 0 && map.reduce((accumulator, currentValue, index) => {
            const count = accumulator + currentValue;
            if (count === maxLength-1 || count === maxLength) {
                n = index;
          }
            if (count > maxLength) {
                e.target.value = split.slice(0, n+1).join('')
                // 控制台输出更改的字符长度
                console.log(e.target.value.length)
          }
            return count
        });
},
    

1.png

可以看到,当输入英文字母(1个英文字母为1字符),会强制截取成10位,随后提交数据。

提交数据后,我查看数据,发现变为了11位。

2.png

于是我查看是后台返回给我的数据有问题,还是我提交给后台的数据有问题。

3.png

发现我这边提交的数据就已经是11位的了,后台返回的数据自然而然也是11位。

问题解决
// html部分
// 将kepup触发的事件中传递的参数,改为v-model绑定的参数
<template slot="remark" slot-scope="action, record">
          <a-input size="small" type="text"  v-model="record.remark" :disabled="pageType=='details'" @keyup="limitLength(record,10)" ></a-input>
</template>
​
// js部分
limitLength(data,maxLength) {
    const value = data.remark
    const split = value.split('');
    const map = split.map((s, i) => {
        return (value.charCodeAt(i) >= 0 && value.charCodeAt(i) <= 128) ? 1 : 2;
    });
        let n = 0;
        const charLength = map.length > 0 && map.reduce((accumulator, currentValue, index) => {
            const count = accumulator + currentValue;
            if (count === maxLength-1 || count === maxLength) {
                n = index;
            }
            if (count > maxLength) {
                data.remark = split.slice(0, n+1).join('')
            }
            return count
        });
},

从解决方案倒退,可以理解我通过input输入框修改v-model双向绑定的值,在v-model接受了值之后,映射到本地仓库,此时接受的值应该是还未通过限制的值,即11位数据。而当用户输入完毕,页面上能显示10位数据,不过通过e.target.value修改的10位数据并没有被v-model劫持,v-model中的数据仍然是11位数据。这让我想到了,在vue中,通过数组下标来修改数组,即使能修改数据,vue无法检测到数据的改变,只能通过数组对象身上的方法类似push(),pop()才能及时渲染。在这个问题中,即使我通过e.target.value修改了input框中的值,vue也无法检测到数据的改变,只有直接更改vue中data的数值时,才能检测到更改并及时渲染。