更新
- 2020/10/8 更新
- 如果是输入文字的时候,将插入内容为空,同时焦点依然是在当前的文本框
- 去掉Formulate组建,直接使用input
- 在加载的时候如果vux中没有短信内容,将页面跳转到login登录
本文主要目标
1、实现六位数字框的排列效果,具体特点是使用flex布局
2、实现六位数字框的脚本控制,输入数字自动跳转到下一数字框
3、实现过60秒后再发送短信码
主要技术要点
1、六个数字框架需要使用脚本进行控制,具体为,设置ref,在method中获得对象;
<div ref="vertifyWrapper">
<FormulateInput input-class="login_input" />
methods
let vertifyInputArray = this.$refs.vertifyWrapper.getElementsByClassName("login_input");
2、设定keyup的事件,主要实现输入以后,自动跳转到下一个数字框,在最后一个输入框,自动将留个框的数字组合,提交post内容
3、设定keydown的事件,主要的目的是避免用户多输入文字
4、六位数字自动排列,主要是使用flex,这里面用到了tailwindcss
(Tailwindcss确实是减少了大量的代码书写,实际使用中是将Tailwind实现大框架,自己的css作为辅助)
<div class="mt-4 flex px-1 text-center item-center" ref="vertifyWrapper">
<FormulateInput v-for="index in 6" :key="index"
outer-class="w-2/12" inputmode="numeric"
/>
</div>
其他技术情况
1、使用了TailwindCss框架快速实现了六个框的排列效果,关于TailwindCss,请参看以前文章(使用普通CSS也可以实现)
【TailwindCSS】帮你快速实现定制CSS的平台【Tailwind CSS】介绍以及在Vue的使用
2、使用了Vue Formulate的表单框架(普通的INPUT配样式也可以)
具体代码
VertifyMobile.vue
<template>
<div class="bg-white w-full fixed h-full">
<NavHeader></NavHeader>
<div class="px-6" style="margin-top:45px;">
<div class="text-center text-jpfont-800 " style="font-weight: 500; line-height:28px; font-size:14px;padding-top:28px;padding-bottom:12px;">
<div class="text-center item-center w-full" style="padding-left: 45%">
<i>
<svg-icon icon-class="vertifycode" class-name="vertifycodeIcon" />
</i>
</div>
<div>验证码将以短信的形式发送给您,请注意接收。</div>
</div>
<div class="ml-2 mt-4 flex px-1 text-center item-center" ref="vertifyWrapper">
<input type="number" v-for="index in 6" :key="index" class="w-2/12 login_input" @keydown='clearInput' @keyup='goVertify'/>
</div>
<div class="mt-8 flex">
<div class="text-sm text-jpcolor-500 pl-3" @click="getVertifycode" :class="[{ hidden: !isShowVertifyCode }]">获取验证码</div>
<div class="text-sm text-jpfont-400 pl-3" :class="[{ hidden: isShowVertifyCode }]">重新发送({{timersecond}})</div>
</div>
</div>
<!-- 提示信息 start -->
<div class="InfoWrapper" :class="[{ hidden: !isShowPromptInfo }, { flex: isShowPromptInfo } ]">
<div style="height:30%;width:100%;"></div>
<div class="mainWrapper">
<div class="text-center item-center w-full" style="padding-left: 40%;margin-bottom: 12px;">
<i>
<svg-icon icon-class="info" class-name="infoIcon" />
</i>
</div>
<div>{{promptInfo}}</div>
</div>
</div>
<!-- 提示信息 end -->
</div>
</template>
<script>
import { mapState } from 'vuex'
import NavHeader from "./NavHeader.vue";
export default {
data() {
return {
inputMobile: "",
isFocus : false,
inputVertifyCode : [],
currentIndex : 0,
isShowVertifyCode: false,
timersecond : 60,
isShowPromptInfo: false,
promptInfo : 'none',
promptTimer:null
};
},
computed: {
...mapState({
vertifyCode: state => state.auth.vertifyCode
})
},
components: { NavHeader },
mounted(){
if(this.vertifyCode === null || this.vertifyCode === 'undefined' || !this.vertifyCode ){
this.$router.push('/login');
}
// 此页面是login跳转页面,在login页面中已经实现了短信码的发送
// 所以在此页面中进入后就默认到第一个输入框
let vertifyInputArray = this.$refs.vertifyWrapper.getElementsByClassName(
"login_input"
);
vertifyInputArray[0].focus();
this.setTimersecond();
console.log(this.vertifyCode);
},
methods:{
showPromptInfo(msg){
this.isShowPromptInfo = true;
this.promptInfo = msg;
this.promptTimer = setTimeout(()=>{
this.isShowPromptInfo = false;
}, 2000);
},
setTimersecond(){
this.timersecond = 60;
var timer = setInterval(()=>{
this.timersecond--;
if(this.timersecond ===0 ){
clearInterval(timer);
this.isShowVertifyCode = true;
}
}, 1000)
},
getVertifycode(){
var dataMobile = { mobile: this.vertifyCode.mobile };
this.$axios
.post("/api/auth/loginvertifycode", dataMobile)
.then(res => {
console.log(res.data);
let _data = res.data;
let _smsid = _data.smsid;
console.log(_smsid);
if(_smsid !== ''){
const sms = {mobile:_data.mobile, smsid:_smsid};
this.$store.commit('setVertifyCode', sms);
let vertifyInputArray = this.$refs.vertifyWrapper.getElementsByClassName(
"login_input"
);
for(let n1=0; n1<vertifyInputArray.length; n1++){
vertifyInputArray[n1].value = '';
}
vertifyInputArray[0].focus();
this.setTimersecond();
}
})
.catch(err => {
console.log(err);
});
},
clearInput(event){
if(event.srcElement.value.toString().length >= 1){
event.srcElement.value = '';
}
},
goVertify(event){
let vertifyInputArray = this.$refs.vertifyWrapper.getElementsByClassName(
"login_input"
);
for(let n1=0; n1<vertifyInputArray.length; n1++){
if(event.srcElement === vertifyInputArray[n1]){
this.inputVertifyCode[n1] = vertifyInputArray[n1].value;
if(n1 === vertifyInputArray.length -1 ){
this.doGovertify();
}
else{
if( vertifyInputArray[n1].value !== '' ){
vertifyInputArray[n1+1].focus();
}
}
}
}
console.log(this.inputVertifyCode)
},
doGovertify(){
const smscode = this.inputVertifyCode.join('');
const smsauth = {
mobile: this.vertifyCode.mobile,
smsid: this.vertifyCode.smsid,
smscode: smscode
};
console.log(smsauth);
this.$axios.post("/api/auth/vertify", {smsauth}).then(res=>{
console.log(res.data);
const rtndata = res.data;
if(rtndata.code === 'ERROR'){
this.showPromptInfo(rtndata.message);
}else if(rtndata.code === 'SUCCESS'){
this.$router.replace("/me");
}
}).catch(err => {
console.log(err);
});
}
}
};
</script>
<style lang="scss" scoped>
.vertifycodeIcon {
color: #e2041b !important;
width: 2.5rem !important;
height: 2.5rem !important;
}
.login_input {
padding-top: 14px;
padding-bottom: 14px;
margin-right:8px;
height: 54px;
width: 45px;
padding-left: 18px;
color: #262626;
font-size: 16px;
border-radius: 0.5rem;
box-sizing: border-box;
line-height: 1;
border: solid 1px #f3f3f3;
outline:none;
background-color: #f3f3f3 !important;
}
.login_input:focus{
border: solid 1px #e60033;
}
.InfoWrapper{
position: absolute;
flex-direction: column;
width: 100%;
height: 100%;
top: 0px;
left:0px;
z-index:50;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.mainWrapper{
margin: 0px 50px 0px 50px;
padding: 18px 16px 16px 16px;
text-align:center;
background-color: #1a202c;
opacity: 0.9;
color: #fff;
font-size:14px;
border-radius: 0.75rem;
}
.infoIcon {
color: #fff !important;
width: 2.5rem !important;
height: 2.5rem !important;
}
</style>
其他
1、此代码在一些环节都还需要优化,但目前主要功能都已经实现,希望对大家能有帮助。
网友评论