目录
前沿:
input的输入限制是一个非常常见的需求,比如我们在一个表单内需要输入时间,则我们就需要限制输入的内容只能是数字,并且是正整数,这如果用表单校验也可以,但是如果直接可以通过input的输入限制,直接讲此扼杀在摇篮中那岂不是美哉下面就是我对一些常见的输入限制的一些总结:(本文的技术栈是Vue3, TypeScript, Vue2可以自行转换)
一、事件的绑定
1.通过input事件绑定并限制输入:
🦋主要是通过@input事件来监听我们的键盘输入并将输入的内容进行劫持处理,过滤来实现整个input按钮的输入过滤。
<el-input v-model="modelValue" @input="inputChange"></el-input>
const modelValue = ref('')
const inputChange = (e:string|null) => {
....限制语句
modelValue.value = e
}
还可以利用$event
来实现对一个对象内的多个变量进行统一的输入过滤方法暴露
<el-input v-model="form.value" @input="handleEdit($event, 'value')"></el-input>
const handleEdit = (e, expr) => {
e = e.replace(/^0(0+)|[^\d]+/g, '')
e = e && Number(e)
this.form[expr] = e
}
2.通过directive自定义指令限制输入:
我们全局定义自定义指令,这边以positive-int
为例,在main.ts内挂载到app后就可以在任何input上绑定,值得注意的是我们一般会用到一些input输入组件,那此事我们在定义🀄️令中获取到的el节点并不是实际的input输入框节点,而是一个封装的组件,别忘了通过dom选择器获取实际的输入框再开始输入限制🚫操作。
<el-input v-model="value" v-positive-int />
const value = ref('')
import type { App } from 'vue'
export const directive = (app: App<Element>) => {
app.directive('positive-int', (el, binding, vnode) => {
// 这将被作为 `mounted` 和 `updated` 调用
// 用于解决element组件获取到的el并不是实际输入框的问题
const input = el.querySelector('.el-input__inner') || el.querySelector('.el-textarea__inner') || el
input.onkeyup = () => {
let { value } = input
............限制语句
input.value = value
input.dispatchEvent(new Event('input'))
}
})
}
main.ts
import { directive } from '@/utils/directive'
const app = createApp(App)
directive(app)
但是这有一个问题就是当你输入比📒🦶较快的时候页面上会出现先出现你输入的内容,然后再被替换掉的情况,但是这是在一瞬间被替换的,如果产品不介意这个情况那也没关系,不得不说自定义指令方式还是非常方便的✈️
3.通过computed方法绑定并劫持数据:
🐯第三种方法是通过computed来劫持变量的变化,通过set属性劫持输入内容,而get属性则直接返回原变量。此方法相较于之前的方法的优势所在就是不会出现原输入显示一下马上被替换掉的情况,因为我们直接对输入的数据就进行了劫持,dom最终拿到的数据是已经被我们替换过的🪚数据了,所以此方法在交互上要优于之前两种方法。
<el-input v-model="currModelValue" ></el-input>
const modelValue = ref('')
const currModelValue = computed({
set(value:string|null) {
// ... 限制语句
modelValue.value = value
},
get() {
return modelValue
}
})
🚀当我们在input框内输入的时候,通过实际测试computed属性劫持会优先于input事件,computed
方法是要优先于input
事件执行的,而且对于输入很快的情况下劫持效果更好,所以我个人推荐是使用computed
方法进行输入的限制以及拦截
二、输入限制
只能输入数字:
条件:正负数,小数都可以🏆
要点:我们通过正则过滤掉所有的除数字和.
以外的字符,但是我们的-号也会被过滤掉,所以我们需要对于第一位的情况进行保存,需要特殊处理的情况:
- 第一位是
-
,需要保留 - 第一位是
.
,直接删除 - 第一位是
-
,第二位是.
直接删除.
- 最后对返回值转为数字类型,转化的时候也要注意,情况不然很容易转化成
NaN
🐷
const currModelValue = computed({
set(value:string|null) {
modelValue.value = getNumber(value)
},
get() {
return modelValue
}
})
const getNumber = (value: string | null | number) => {
let str = `${value ?? ''}` // ?? 不会过滤到0
const char1 = str.charAt(0)
const char2 = str.charAt(1)
if (char1 === '.') str = ''
if (char1 === '-' && char2 === '.') str = '-'
str = str.toString() // replace()方法是字符串方法
.replace(/[^\d.]/g, '')
.replace(/\.{2,}/g, '.')
.replace('.', '$#$')
.replace(/\./g, '')
.replace('$#$', '.')// 只能输入一个小数点
value = (str[str.length - 1] === '.' || !str) ? char1 === '-' ? char1 + str : str : parseFloat(char1 === '-' ? char1 + str : str)
return value
}
只能输入整数:
条件:可以输入正负整数、0
🦕这里是需要保存-
进行特殊处理即可,其他的非数字符号全部过滤掉
const getInit = (value: string | null | number) => {
let str = `${value ?? ''}`
const char = str.charAt(0)
// 先把非数字的都替换掉
str = str.replace(/[^\d]/g, '')
// 如果第一位是负号,则允许添加
if (char === '-')
str = `-${str}`
value = str[str.length - 1] === '-' || !str ? str : parseFloat(str)
return value
}
只能输入正数:
条件:正整数、正小数和0可以输入
const getPositiveNumber = (value: string | null | number) => {
let str = `${value ?? ''}`
if (str && str[0] === '.') str = ''
str = str.toString() // replace()方法是字符串方法
.replace(/[^\d.]/g, '')
.replace(/\.{2,}/g, '.')
.replace('.', '$#$')
.replace(/\./g, '')
.replace('$#$', '.')// 只能输入一个小数点
value = (str[str.length - 1] === '.' || !str) ? str : parseFloat(str)
return value
}
只能输入负数:
条件:负整数,负小数可以输入,0不可以输入
const getNegativeNumber = (value: string | null | number) => {
let str = `${value || ''}`
const char1 = str.charAt(0)
if (char1 !== '-') str = ''
str = str.toString() // replace()方法是字符串方法
.replace(/[^\d.]/g, '')
.replace(/\.{2,}/g, '.')
.replace('.', '$#$')
.replace(/\./g, '')
.replace('$#$', '.')// 只能输入一个小数点
value = (str[str.length - 1] === '.' || !str) ? char1 === '-' ? char1 + str : str : parseFloat(char1 === '-' ? char1 + str : str)
return value
}
只能输入正整数:
条件:正整数和0可以输入,同v-model.number
,但是比如012
会被过滤成12
const getPositiveInt = (value: string | null | number) => {
const num = parseFloat(value as string)
value = Object.is(num, NaN) ? null : num
return value
}
const getPositiveInt = (value: string | null | number) => {
value = value.replace(/^0(0+)|[^\d]+/g, '')
value = value && Number(value)
return value
}
只能输入负整数:
条件:负整数可以输入,不可以输入0
const getNegativeInt = (value: string | null | number) => {
const str = `${value || ''}`
if (str.length === 1 && str[0] === '-') {
//
}
else {
const num = parseFloat(str)
if (Object.is(num, NaN))
value = null
else value = num
}
return value
}
只能输入3位
const getLimitNum = (value: string | null | number) => {
const str = `${value ?? ''}`
return str.length > 3 ? str.slice(0, 3) : value
}
三、校验
电话号码校验:
(/^1[3456789]\d{9}$/).test(str)
身份证:
(/^[0-9,X]{18}/).test(str)
🚀🐛🐛🐛会持续更新…
以上如果有各位如果有更好的写法以及要补充的可以发我哦!