一直都想搞一个能够统一处理input框限制的小工具,最近新项目有需要,就借鉴了一下大佬们的文档博客,自己记录一下。
废话不多说,直接上代码:
//index.vue
<template>
// 纯数字
<el-input v-input-filter:num="ruleForm.warningNum" v-model="ruleForm.warningNum" placeholder="请输入数字"></el-input>
// 纯数字 + 小数点
<el-input v-input-filter:num.point="ruleForm.warningNum" v-model="ruleForm.warningNum" placeholder="请输入数字"></el-input>
</template>
// directive.js
import Vue from 'vue'
// 限制只能输入数字 小数点的限制由修饰符控制
const onlyNum = (el, bindings, vnode) => {
let regExp = /[^\d]/g
if (bindings.modifiers['point']) {
// 修饰符 ‘point’
regExp = /[^\d\.]/g
}
fnSaveCursorPos(el, bindings, vnode, regExp)
}
// 限制只能输入字母(包含大小写字母)
const onlyLetter = (el, bindings, vnode) => {
let regExp = /[^a-z|A-Z]/g
if (bindings.modifiers['point']) {
// 修饰符 ‘point’
regExp = /[^a-z|A-Z|.]/g
}
fnSaveCursorPos(el, bindings, vnode, regExp)
}
// 限制只能输入字母和数字(包含大小写字母)
const onlyLetterNum = (el, bindings, vnode) => {
let regExp = /[^a-z|A-Z\d]/g
fnSaveCursorPos(el, bindings, vnode, regExp)
}
Vue.directive('input-filter', {
update(el, bindings, vnode) {
switch (bindings.arg) {
case 'num':
onlyNum(el, bindings, vnode)
break
case 'letter':
onlyLetter(el, bindings, vnode)
break
case 'num-letter':
onlyLetterNum(el, bindings, vnode)
break
default:
console.log('此方法暂无增加')
break
}
}
})
// 处理光标位置,避免重新赋值之后光标出现在末尾
function fnSaveCursorPos(el, bindings, vnode, regExp) {
bindings.value = bindings.value + ''
let inputEl = el
if (el.tagName !== 'INPUT') {
inputEl = el.querySelector('input')
}
if (!inputEl) {
console.log('没有input')
return
}
const inputElCursorPos = inputEl.selectionStart // 输入框输入之后的光标位置
const regExpStringLength = (bindings.value.match(regExp) || []).length // 被清除的字符长度
fnSetVal(vnode.context, bindings.expression, bindings.value.replace(regExp, ''))
inputEl.setSelectionRange(inputElCursorPos - regExpStringLength, inputElCursorPos - regExpStringLength)
const timer = setTimeout(() => {
// console.log('inputEl', inputElCursorPos - regExpStringLength)
clearTimeout(timer)
inputEl.setSelectionRange(inputElCursorPos - regExpStringLength, inputElCursorPos - regExpStringLength)
})
}
// 赋值处理, 例如:obj.key.key
function fnSetVal(data, fields, setVal) {
if (Object.prototype.toString.call(data) === '[object Object]' && Object.prototype.toString.call(fields) === '[object String]') {
const keys = fields.split('.')
let value = data
while (keys.length && value !== undefined) {
if (keys.length === 1) {
value[keys[0]] = setVal
return
}
value = value[keys[0]]
keys.shift()
}
}
}
利用自定义指令中‘更新’的生命周期来对绑定的值进行处理,但是这个会有两次的更新过程,第一次是原始值触发更新,第二次是处理限制之后触发的更新;感觉这里有点不太完美。
文章中如果有什么问题,欢迎指出~~~ 感谢!!!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。