小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
本文同时参与「掘力星计划」,赢取创作大礼包,挑战创作激励金
前言
前面我们已经讲了一个点击自动复制文本的自定义指令。今天我们再来说一个关于限制输入的自定义指令。 先来了解一下什么是限制输入呢?其实就是针对用户的输入行为做一个合理合法的校验,排除一些不符合规则的输入。在h5的input标签中已经为我们提供了一些输入限制的类型,比如color,date,email,number,tel等等,如果是一些简单的输入验证,使用这些自带的类型已经足够了。然鹅,有时候根据一些业务需要,这些单一的输入限制可能无法满足我们的业务需求,这时就不得不定制一套灵活的输入限制了。如果仅仅是一个控件需要做限制,那么完全可以直接写在控件的keyup或者change事件中就可以了,但是如果想要做成一个通用的,想在哪用就在哪用的灵活的插件,那么这个时候封装一个自定义指令是再好不过了。下面我们就以一个只能输入字母和数字的输入限制为例,实现一个简单的输入限制自定义指令。
思路分析
输入限制相对前面讲过的自动复制还要简单一些,整个过程我们只需要用到2个钩子函数:一个是beforeMount用于在指令第一次绑定时给元素添加keyup事件并处理非法输入的逻辑,另一个是unmounted用于移除元素的keyup事件
- beforeMount:指令第一次绑定元素前
- 给要绑定的元素el添加keyup事件
- 在keyup的回调函数中接收自定义指令的限制规则(程序开发时可以将限制规则通过指令值的形式传给指令,如v-emoji="[^a-zA-Z0-9]/g")
- 将不符合限制规则的非法字符替换并重新赋值给元素的value
- unmounted:指令解绑后同时移除元素的keyup事件
通过以上简单的两步就实现了一个简单的输入限制,下面我们来看一下具体代码
输入限制代码
<input type='text' v-emoji="'[^a-zA-Z0-9]'" v-model='dataText' />
<span>{{dataText}}</span>
const app = createApp();
app.directive('emoji',{
beforeMount(el, binding){
//keyup事件回调函数,便于后续删除
el.$handle = function(){
let val = el.value;//input输入框的value
let reg = new RegExp(binding.value);//指令的限制规则
el.value = val.replace(reg,'');//不符合规定的字符替换
}
el.addEventListener('keyup', el.$handle);
},
unmounted(el){
el.removeEventListener('keyup', el.$handle);
}
});
优化
上面的代码从表面上看貌似是已经实现了我们的需求。然鹅这里还有个问题:如果将上面的代码运行起来,你会发现当我们在文本框中输入一个特殊字符时,文本框中会立即把特殊字符值删除掉,但是下面的span却依然还保留着特殊字符。这是因为在上面的代码中我们在把特殊字符替换掉后直接赋值给了input的value属性,这时并没有触发文本框的input事件。而了解v-model原理的小伙伴应该都知道,v-model之所以能够实现双向绑定,是因为v-model会监听文本框的input事件,当input被触发时会去更新对应的属性值。而我们代码中的替换值操作并没有触发input事件。 那么找到了问题的原因,也就好解决了,我们只需要在代码中触发一些input事件就可了,下面来看一下优化后的完整代码。
const app = createApp();
const trigger = function trigger(el,type){
let ev = document.createEvent('HTMLEvents');//创建HTML事件
ev.initEvent(type,true,true);//初始化事件,type为事件类型,如input
el.dispatchEvent(ev);//派发事件
}
app.directive('emoji',{
beforeMount(el, binding){
//keyup事件回调函数,便于后续删除
el.$handle = function(){
let val = el.value;//input输入框的value
let reg = new RegExp(binding.value);//指令的限制规则
el.value = val.replace(reg,'');//不符合规定的字符替换
//同步到响应式数据中
trigger(el, 'input');//触发元素是input事件
}
el.addEventListener('keyup', el.$handle);
},
unmounted(el){
el.removeEventListener('keyup', el.$handle);
}
});
总结
本文我们对输入限制的自定义指令进行了一个简单的介绍和实现思路分析,并简单了实现了一个只允许输入数字字母的自定义指令,最后还发现了一个双向绑定的问题并提出了优化方案。 本文就到这里,欢迎喜欢的小伙伴点赞关注加留言哦!