今天看到一个帖子,说到用input输入框模拟滴滴、摩拜等app验证码输入效果,提到了一个方案:
1、利用input来获得焦点,自动调用手机的数字键盘
2、实际将输入框用透明度隐藏
3、用label的for属性与input联动来显示输入的数字
于是照着这个思路实际操作了一番,还是发现了不少问题。
首先页面布局:
<div class="container"> <h2>输入验证码:</h2> <div class="vcode" id='vertifycode'> <input type="tel" maxlength='6' ref='code' class='code' id='code'> <div class="labels"> <label class='label' for="code"></label> <label class='label' for="code"></label> <label class='label' for="code"></label> <label class='label' for="code"></label> <label class='label' for="code"></label> <label class='label' for="code"></label> </div> </div> </div>
样式:
@keyframes animate { 100% { opacity: 0; } } .container{ padding: 5%; } .vcode{ position: relative; width: 100%; overflow: hidden; } .code{ width: 100%; padding: 0; height: 40px; font-size: 35px; overflow: hidden; border: none; outline: none; opacity: 0; margin-left: -100%; // ios上透明度为0时依然有光标 -webkit-tap-highlight-color: transparent; } .labels{ display: flex; display: -webkit-flex; width: 100%; height: 40px; justify-content: space-between; -webkit-justify-content: space-between; margin-top: -40px; -webkit-tap-highlight-color: transparent;// 解决ios点击灰色阴影的问题 } .label{ height: 34px; width: 12%; border-bottom: solid 2px #313131; float: left; color: #313131; font-size: 35px; text-align: center; padding-bottom: 4px; } .active:after{ // 伪类实现光标效果 content: ' '; display: inline-block; height: 100%; width: 2px; background: #313131; animation: .8s animate infinite; }
注意点:
1、ios手机上input和lable都会出现点击有灰色背景闪动的问题,所以一定要给样式加上
-webkit-tap-highlight-color: transparent;
2、输入框的默认光标隐藏了后,用伪类实现光标效果:
.active:after{ // 伪类实现光标效果 content: ' '; display: inline-block; height: 100%; width: 2px; background: #313131; animation: .8s animate infinite; }
3、ios上虽然input透明度已经设置为0了,但是当其获得焦点时,默认的光标依然存在
可以利用margin将整个input输入框隐藏来解决:
margin-left: -100%;
样式写好了,就改进行逻辑处理了:
引入vue.js(vue确实好用)
<script src='./js/vue.min.js'></script>
更改页面布局:
<div class="container"> <h2>输入验证码:</h2> <div class="vcode" id='vertifycode'> <input type="tel" maxlength='6' ref='code' class='code' id='code' @focus='focus=true' v-model='code' @blur='focus=false' :disabled='disabled' > <div class="labels"> <label class='label' for="code" :class='{active: focus===true && index===currentIndex}' v-for='item,index in length' v-text='arrCode[index]'> </label> </div> </div> </div>
逻辑代码:
new Vue({ el: '#vertifycode', data: { length: 6, currentIndex: 0, code: '', focus: false, arrCode: [], disabled: false }, computed: { arrCode: function () { return this.code.split(''); }, currentIndex: function () { return this.code.length; } }, watch: { code: function (newV,oldV) { var self = this; this.code = newV.replace(/[^\d]/g,''); // 限制非数字 console.log(newV); if(newV.length >= 6) { this.disabled = true; this.$refs.code.blur(); setTimeout(function () { alert('submit:'+self.code+''); },500); } } }
数据说明:
length: 密码长度,根据实际需求设定;
currentIndex: 当前获得焦点的label的索引;
code: 输入的内容;
focus: 判断输入框的焦点状况;
arrCode:用于填充label标签内容;
disabled:控制输入框是否可用,输入6位验证码后禁用。
当输入长度等于6时,输入框失去焦点,自动提交数据,弹出提示框,实际效果: