使用<input>标签实现六个格子验证码输入框

用户头像
brave heart
关注
发布于: 2020 年 05 月 28 日
使用<input>标签实现六个格子验证码输入框

前言

现在的需求是要实现一个六个格子验证码输入框,本来是想直接在网上找现成的轮子的,但是找了一圈没发现可以让我满意的,那就试着自己摸索了。

效果图





功能需求

  1. 只支持纯数字输入,我们知道如果input设置typenumber时,其实是可以输入自然常数e这个英文字母的,而且对于处理这种纯数字输入,如果处理不当,在中文模式下打出拼音,这时,切换中英文经常出现输入了英文字母的现象。

  2. 在前一个输入框输入完成,光标自动移动至下一个输入框。

  3. 按下BackSpace键,清空当前输入框内容,光标自动移动至上一个输入框。

  4. 没有输入完整,会在下方出现“请输入验证码”提示。

实现过程

一开始是打算使用element-ui组件库里的el-input组件来实现的,但是因为样式的原因,就作罢了,还有就是想着只用一个input能不能来实现这个功能,但是研究了一番,还是没能成功,最后就是现在这个,使用了六个input来实现,样式方面问题不大,就不多说明了,主要是功能层面,验证码输入,那一定就是只能是数字了,那么首要解决的当然就是限制输入,只能允许用户输入数字,如下代码所示:

 

oninput="value=value.replace(/[^\d]/g,'')"

当用户输入的是非数字时,默认会替换成空字符串,也就达到了限制输入,只能输入纯数字的目的。

接着,我们来看一下第二点的需求,要实现这个功能,就需要知道什么时候让当前输入框失去焦点,并且同时让下一个输入框获取焦点,让一个输入框获取焦点,其实可以使用vue.js里的ref属性来实现,代码如下所示:

 

this.$refs.input.focus()

但是现在是使用v-for来遍历生成六个input的,如果要设置ref属性,那怎么区分这六个input,代码如下所示:

 

:ref="`ref${index}`"

直接是通过index来设置,实现六个input不同的ref命名的,然后就是在v-for中使用ref会遇到的问题了,在vue.js官网中,我们可以看到,有这样一句话:

 

当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。

也就是说,在v-for中,你如果是这样使用ref的话是无效的,并不能正确的获取到对应的第一个input的属性,代码如下所示:

 

this.$refs.ref0.focus()

所以,你需要修改为这种方式来使用,代码如下所示:

 

this.$refs['ref0'][0].focus()

至此,第二点需求,就好解决了,代码如下所示:



@input="onInput(index)"
......
onInput (index) {
// index < 5 ,如果是第6格,不触发光标移动至下一个输入框。
if (this.inputbox[index].value && index < 5) {
this.$refs['ref' + (index + 1)][0].focus()
}
}

以此类推,第三点需求,也跟着解决了,代码如下所示:

@keyup.delete="onDelete(index)"
......
onDelete (index) {
// 如果是第1格,不触发光标移动至上一个输入框
if (index > 0) {
this.$refs['ref' + (index - 1)][0].focus()
}
}

至于第四点需求,其实只要通过判断输入值的长度来判断即可,那就是如果输入了,但是没有完整输入六位验证码,那么就提示用户,代码如下所示:

var inputValue = ''
this.inputbox.forEach(item => {
inputValue = inputValue + item.value
})
if (inputValue.length < 6) {
this.isError = true
} else {
this.isError = false
}

写在最后

其实,说到底这个功能很一般,感觉根本没什么难度,之所以选择很认真的去记述这样的一个过程,主要还是知道苍蝇虽小,五脏俱全,小的事情能够做好,那么大的事情才能有底气去完成。而且,很多事情,都是有规律的,往往可以举一反三,再说了,想要能够在某个方面有所建树,不是一蹴而就的,往往都是经过长年累月的努力,一点点打磨和沉淀的,所以,我现在能做的,只是尽自己所能,可以把一个东西讲清楚,把整个逻辑理清,这就算是很不错的收获了。

完整代码

<template>
<div>
<div class="six-input-box">
<input v-for="(item,index) in inputbox"
:key="index"
:ref="`ref${index}`"
class="input"
v-model="item.value"
type="text"
oninput="value=value.replace(/[^\d]/g,'')"
@input="onInput(index)"
@keyup.delete="onDelete(index)"
maxlength="1" />
</div>
<span class="error-tips"
v-if="isError">请输入六位验证码</span>
</div>
</template>
<script>
export default {
data () {
return {
inputbox: [
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
}
],
isError: false
}
},
methods: {
onInput (index) {
// index < 5 ,如果是第6格,不触发光标移动至下一个输入框。
if (this.inputbox[index].value && index < 5) {
this.$refs['ref' + (index + 1)][0].focus()
}
var inputValue = ''
this.inputbox.forEach(item => {
inputValue = inputValue + item.value
})
if (inputValue.length < 6) {
this.isError = true
} else {
this.isError = false
}
},
onDelete (index) {
// 如果是第1格,不触发光标移动至上一个输入框
if (index > 0) {
this.$refs['ref' + (index - 1)][0].focus()
}
}
}
}
</script>
<style scoped>
.six-input-box {
display: flex;
flex-direction: row;
}
.input {
display: flex;
width: 25px;
margin-left: 10px;
height: 44px;
font-size: 18px;
color: #333333;
background-color: #f2f2f2;
text-align: center;
outline: none;
border: solid 1px #d2d2d2;
border-top: 0px;
border-left: 0px;
border-right: 0px;
}
.error-tips {
margin-left: 10px;
color: #f56c6c;
font-size: 12px;
}
</style>



示例代码:https://github.com/BRAVE2HEART/infoq-vue-example



发布于: 2020 年 05 月 28 日 阅读数: 131
用户头像

brave heart

关注

唯一不变的是变化本身。 2018.04.17 加入

🗡 她只唱只想这首止战之殇。

评论

发布
暂无评论
使用<input>标签实现六个格子验证码输入框