浅谈vue限制文本框输入数字的正确姿势

2020-06-12 21:15:48易采站长站整理

if (pointKeep === 0) {
// 不需要小数点
+ val = val.replace(reg, '$1$2')
} else {
// 通过正则保留小数点后指定的位数
+ val = val.replace(reg, '$1$2.$3')
}
}
} else {
val = ele.value.replace(/[^d]/g, '')
}
ele.value = val
}

支持输入的最大值和最小值的限制

指令的参数支持对象的传递,因此这边我们通过对象的字段配置最大数和最小值的配置。定义如下:


{
min: {type: number},
max: {type: number},
// 最大小数位,仅在float下有效
decimal: {type: number}
}


function handle() {
let val = ele.value
// modifiers为修饰符对象,传入了float,则其float属性为true
if (binding.modifiers.float) {
// 清除"数字"和"."以及"-"以外的字符
val = val.replace(/[^-d.]/g, '')
// 只保留第一个'-'号
val = val.replace(/.{2,}/g, '.').replace(/-{2,}/g, '-')
// 将 '-.' 替换成 '-0.'
val = val.replace(/^./g, '0.').replace(/^-./, '-0.')
if (typeof binding.value !== 'undefined') {
// 期望保留的最大小数位数
let pointKeep = 0
if (typeof binding.value === 'string'
|| typeof binding.value === 'number') {
pointKeep = parseInt(binding.value)
+ } else if (typeof binding.value === 'object') {
+ // 支持新的小数点保留位配置
+ pointKeep = binding.value.decimal
}
if (!isNaN(pointKeep)) {
if (!Number.isInteger(pointKeep)
|| pointKeep < 0) {
pointKeep = 0
}
// 增加'-'号的支持
const str='^(-)*(d+).(d{' + pointKeep + '}).*$'
const reg=new RegExp(str)
if (pointKeep === 0) {
// 不需要小数点
val = val.replace(reg, '$1$2')
} else {
// 通过正则保留小数点后指定的位数
val = val.replace(reg, '$1$2.$3')
}
}
} else {
val = ele.value.replace(/[^d]/g, '')
}
+ if (val !== '' && typeof binding.value === 'object') {
+ let { min, max } = binding.value
+ min = parseFloat(min)
+ max = parseFloat(max)
+ if (!isNaN(min)) {
+ if (min >= 0) {
+ // 不能是负数
+ val = val.replace('-', '')
+ }
+ if (parseFloat(val) < min) {
+ val = min
+ }
+ }
+ if (!isNaN(max)) {
+ if (parseFloat(val) > max) {
+ val = max
+ }
+ }
+ }
ele.value = val
}

使用方法:


// 最小为0
<el-input v-model="model" v-number-input="{ min: 0 }" />

结语

至此我们的功能已经实现得差不多了,上述代码已经足以应对我们的大多数的需求了。但在我发现某些场景下有的时候键入非数字时,表单验证获取的数值仍然是我键入的字符而非空值,导致非空验证不正确。但是这种情况并非必现的,我猜想可能是因为是vue的model数据未同步导致的,因此在上述回调函数添加上以下代码,手动触发数据的双向绑定。