移动端项目 需求是 输入框只能输入1000以内的数字保留两位小数 开发中发现 用vue开发双向绑定 不管是用value还是v-model 在输入时用@input监听输入框变化 校验是否匹配 当不匹配是修改绑定的变量 inputValue时 打印inputValue符合预期 但是input输入框中还是原来输入的值 没有随inputValue这个变量进行修改
后来想到 用 disabled 当输入的值不通过校验时 禁用输入框 然后延迟几百毫秒再取消禁用 结果禁用后输入框失去焦点 收起键盘了 所以不合适
接下来想到 用 readonly 不通过校验时变成只读 这样就不能输入了 但是焦点还在键盘没有收起 还是符合预期的
但是偶然发现小程序中 input 不支持 readonly 开始时成功了是因为延迟赋值inputValue
最后 干掉了readonly 只用延迟修改赋
值inputValue 就实现了功能
关于保留两位小数的方法也找了很多 正则验证 值了的 测试时都不是很符合预期 就自己写了一些判断 并且加上延迟赋值时不执行方法
以下是部分代码 只是自己的思路 有什么更好的方法 希望能联系我
<input class="other-input" type="digit" maxlength="6" v-model="inputValue"
placeholder="请输入¥1000内任意金额" @input="inputChange">
// 绑定的变量
const inputValue: any = ref()
// 限制的状态 默认false
const awaitInputTime = ref(false)
// @input 方法
const inputChange = (event: any) => {
let value = event.detail.value
if (awaitInputTime.value) return
// 优先判断有没有小数点 value.match(/(\.)/g)
// 匹配非数字、非小数点和非空格的字符 regex.test(value)
// 判断是否大于某个值 Number(value) > 1000
const regex = /[^\d.]|^\.|\.$/g;
if (value.match(/(\.)/g) || regex.test(value) || Number(value) > 1000) {
awaitInputTime.value = true //设置限制状态 当不符合时为了节流
setTimeout(() => { //延迟
const firstIndex = value.indexOf('.'); // 获取第一个小数点位置
const lastIndex = value.lastIndexOf('.');// 获取最后小数点位置
// 当第一个小数点存在 并且第一个和最后一个不相等 干掉最后一个小数点
if (firstIndex >= 0 && firstIndex != lastIndex) value = value.slice(0, -1)
// 当小数点存在 并且小数点后的位数大于两位 干掉最后一个字符
if (firstIndex >= 0 && value.split('.')[1].length > 2) value = value.slice(0, -1)
// 当大于最大值 让value等于最大值
if (Number(value) > 1000) value = '1000'
// 替换所有非是数字
inputValue.value = value.replace(/[^0-9.]/g, '')
// 解除节流限制
awaitInputTime.value = false
// 延迟10毫秒就可以重新渲染输入框
}, 10)
} else {
//完全符合规则执行的内容
}
}