Vue

【经验分享】VUE中短信验证码六位数字框输入设计

2020-10-07  本文已影响0人  度一特

更新

  1. 2020/10/8 更新

本文主要目标

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、此代码在一些环节都还需要优化,但目前主要功能都已经实现,希望对大家能有帮助。

上一篇 下一篇

猜你喜欢

热点阅读