背景
数字输入框限制其它符号的输入是一个很常见的需求,但是网上的实现方案始终离理想状态差那么一丢丢,大多会遇到两个坑,一个是 type=number
并不能过滤加减符号,另外一个点就是如果需要能够输入小数时,如何限制首位禁止输入多个0,并且能够正确的过滤保留位数
本篇就带大家一起一步一步,通过实现这个需求,到最终掌握各项基础的正则小知识
思路
首先我们来对两个难点进行分析看看如何解决
能不能使用 type = number
如果你的需求要求输入时限制用户把加减符号输入进去,那么答案是肯定的,不能
通常我们在实现输入限制时会配合 input
事件对输入进行实时处理,如果使用 type=number
,那么遇到诸如 +,-
之类的运算符号时,事件结果会直接返回空,这样会导致我们的正则匹配失效,所以实现这个需求的第一步,我们需要把 input
上的类型属性设置为 text
,以 element-ui
为例
<el-input v-model="number" type="text"></el-input>
各种需求情况下正则怎么写
这里可以先按几种简单的类型来实现,最后组装为我们想要的结果,大家也可以按自己的需求进行魔改,我们的代码逻辑大概是这个样子
<el-input v-model="number" type="text" @input="handleInput"></el-input>
const number = ref()
const handleInput = (value) => {
// 用来匹配的正则
const reg = /{期望正则}/g
// input 变量保存替换结果
let input = value.replace(reg,'')
// 将替换结果赋值给绑定对象
number.value = input
}
只允许输入正整数
不允许输入0以及运算符号,
eg: +,-,.
使用 \D
匹配非数字
使用 ^0
匹配首位的0
const handleInput = (value) => {
// 匹配非数字清除
const reg = /\D|^0/g
let input = value.replace(reg,'')
number.value = input
}
只允许输入整数
允许输入0,但开头不可以输入连续0,
eg: 012
使用 \D
匹配非数字
使用 /^0+(\d)/
匹配开头的连续0,并获取0后第一个数字用于替换0
const handleInput = (value) => {
// 匹配非数字清除
const reg = /\D/g
let input = value.replace(reg,'')
// 匹配开头的连续0,用第一个数字替换
const reg1 = /^0+(\d)/
input = input.replace(reg1, '$1')
number.value = input
}
允许输入小数
同样不允许输入各种加减号,这里主要是首位和连续的小数点需要处理
- 使用
[^\d.]|^.
匹配非数字和小数点之外的输入,并且首位不能是小数点
[] 中括号表示匹配字符类
^ 在字符类中表示取反(注意这里第一个^就不是取首位了)
\d. 表示匹配数字和小数点
const reg = /[^\d.]|^./g
let input = value.replace(reg,'')
- 如果输入多个小数点,只保留第一个
这里借鉴一下网上的一些思路,总结来说就3步
第一步,匹配到第一个小数点,进行特殊字符的替换(这里用 $#$
)
input = input.replace('.', '$#$')
第二步,匹配其余所有小数点,进行删除
input = input.replace(/./g, '')
第三步,把第一步的$#$
还原成小数点
input = input.replace('$#$', '.')
三步合并下
input = input.replace('.', '$#$').replace(/./g, '').replace('$#$', '.')
最终结果(加上之前的不可输入连续0)
const handleInput = (value: any) => {
const reg = /[^\d.]|^./g
let input = value.replace(reg,'')
input = input.replace('.', '$#$').replace(/./g, '').replace('$#$', '.')
const reg1 = /^0+(\d)/
input = input.replace(reg1, '$1')
number.value = input
}
只允许输入指定精度的数字(这里以2位为例)
到这里已经很明朗了,只需要在上面的基础上稍加修改即可
思路是对小数点两侧进行分组匹配在将结果返回
第一步,匹配小数点左侧 ^(\d+)
第二步,匹配小数点 .
第三步,匹配小数点右侧 (\d\d)
(如果更多位,增加\d
即可)
第四步,.*$
对余下字符进行匹配,最后使用$1, $2
取到分组结果进行组合替换
合并下
const reg3 = /^(\d+).(\d\d).*$/
input = input.replace(reg3, '$1.$2')
最终结果
const handleInput = (value: any) => {
const reg = /[^\d.]|^./g
let input = value.replace(reg,'')
input = input.replace('.', '$#$').replace(/./g, '').replace('$#$', '.')
const reg2 = /^0+(\d)/
input = input.replace(reg2, '$1')
const reg3 = /^(\d+).(\d\d).*$/
input = input.replace(reg3, '$1.$2')
number.value = input
}
小结
看到这,相信你对输入框的限制输入需求如何实现已经有了大体的思路,也对各种常见的正则匹配小技巧有所了解了,简单梳理下
\d
匹配数字\D
匹配非数字^
标记第一个+
匹配多个[]
匹配字符串中的某一类字符()
对匹配结果分组,可以使用 $ 符号获取匹配结果.*$
匹配余下所有
希望大家看完都能好好消化消化,相信不管对完成这个需求,还是加深对正则的理解,都会有所帮助的^_^