js 输入短信验证码4位 & 6位 vue前端

本文介绍了一个基于Vue的自定义短信验证码输入组件实现方法,通过HTML和CSS实现了美观的验证码输入界面,并利用Vue的特性实现了输入长度限制及光标定位等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue开发 输入短信验证码输入6位 或者4位

不使用插件情况下,效果图如下图所示

样式如图

// html
<div class="code">
	<div class="v-code">
		<label
			for="vcode"
            class="line"
            v-for="(item, index) in codeLength"
            :key="index"
            :class="{ animated: focused && cursorIndex === index }"
            v-text="codeArr[index]"
		>
		<!-- animated类名 css3模拟光标事件 -->
        </label>
          <input
            ref="vcode"
            id="vcode"
            type="tel"
            autocomplete="off"
            maxlength="6"
            v-model="code"
            @click="focusEnd('vcode')"
            @focus="focused = true"
            @blur="focused = false"
            @keyup.enter="next"
          /> 
          <!-- 如果是4位验证码 maxlength="4" -->
          <!-- @keyup.enter回车事件绑定下一步操作 -->
	</div>
</div>
<div :class="[show ? 'code-dark' : 'code-resend']">
	<!-- resend 重新验证请求接口事件 -->
	<span @click="resend">{{ 发送 }}</span>
	<!-- 倒计时60秒 重新验证 -->
	<span v-if="show"> ({{ fixZero(count) }}) </span>
</div>
// ------------------
// js部分
// data数据
// 定义倒计时时间 没必要放data 不需要双向绑定
const defaultTime = 60;
// 时间补零
const fixZeros = num => {
    const a = num + '';
    return a.length === 2 ? a : `0${a}`;
}
export default {
  name: "verification",
  data() {
	return {
		code: "",
      	codeLength: 6,  // 如果是4位验证码 在这设置
      	focused: false,
      	count: "",  
      	show: false,
      	timer: null,
	}
}
// watch 监听
watch: {
    code: {
      handler(newVal) {
        this.code = newVal.replace(/[^\d]/g, "");
        // 当输入第六位验证码光标停留在第六位字符后 
        // 若是4位验证码 .length>3
        if (newVal.length > 5) {
       	  // 不需要光标停留在最后一位字符 this.$refs.vcode.blur();
          this.$nextTick(() => {
            // 兼容IE浏览器 使光标显示在文字后
            document.styleSheets[0].addRule(
              ".animated::before",
              "left: 62% !important;"
            );
            // 支持非IE的现代浏览器
            document.styleSheets[0].insertRule(
              ".animated::before { left: 62%  !important;}",
              0
            );
          });
        } else {
          this.$nextTick(() => {
            document.styleSheets[0].addRule(
              ".animated::before",
              "left: 50% !important;"
            );
            document.styleSheets[0].insertRule(
              ".animated::before { left: 50%  !important;}",
              0
            );
          });
        }
      },
      immediate: true,
    },
},
// mounted 挂载
mounted() {
	this.$refs && this.$refs.vcode.focus();
},
// 计算属性
computed: {
    codeArr() {
      return this.code.split("");
    },
    cursorIndex() {
    	// 输入最后一位光标依然存在,不需要则设置
    	// return this.code.length
      const len = this.code.length === 6 ? 5 : this.code.length;
      return len;
    },
},
// methods 定义的方法
methods: {
    // 默认input的focuse在最后
    focusEnd(id) {
      var inpEl = document.getElementById(id);
      inpEl.focus();
      var length = inpEl.value.length;
      if (document.selection) {
        var range = inpEl.createTextRange();
        range.moveStart("character", length);
        range.collapse();
        range.select();
      } else if (
        typeof inpEl.selectionStart === "number" &&
        typeof inpEl.selectionEnd === "number"
      ) {
        // selectionStart和selectionEnd两个属性是当前选中文本起始位置的索引
        inpEl.selectionStart = inpEl.selectionEnd = length;
      }
    },
    next() {
      if (!this.code) return;
      if (this.code.length < 6) {
        this.$toast('邮箱格式错误');
        return;
      }
      ... // 写接口请求
    },
    // 重新发送接收验证码的请求接口
    resend() {},
    // 显示剩余时间
    fixZero(time) {
      return fixZeros(time);
    },
    // 倒计时
    countDown() {
      this.count = defaultTime;
      if (!this.timer) {
        this.count = defaultTime;
        this.show = true;
        this.timer = setInterval(() => {
          if (this.count > 0 && this.count <= defaultTime) {
            this.count--;
          } else {
            this.show = false;
            clearInterval(this.timer);
            this.timer = null;
          }
        }, 1000);
      }
    },
// 路由守卫 判断进入组件是否指定组件 定时器开始
beforeRouteEnter(to, from, next) {
    if (from.name === "Email") {
      next((vm) => {
        // 定时器
        vm.countDown();
      });
    } else {
      next();
    }
 },
// 路由守卫 离开组件清掉计时器
beforeRouteLeave(from, to, next) {
    next();
    clearInterval(this.timer);
},

.code {
  width: 100%;
  margin-bottom: 0.2rem;
}
.v-code {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  position: relative;
}
.v-code input {
  position: absolute;
  opacity: 0;
  height: 100%;
  width: 100%;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.v-code .line {
  position: relative;
  width: 0.4rem;
  height: 0.4rem;
  background: #f5f6fa;
  border-radius: 0.04rem;
  line-height: 0.4rem;
  text-align: center;
  font-size: 0.24rem;
  color: #2f3033;
}
.v-code .line.animated {
  background-color: #fff;
  border-radius: 0.04rem;
  border: 1px solid #0072f5;
}
.v-code .line.animated::before {
  display: block;
  position: absolute;
  left: 50%;
  top: 20%;
  width: 1px;
  height: 60%;
  content: "";
  background-color: #333;
  animation-name: coruscate;
  animation-duration: 1s;
  animation-iteration-count: infinite;
  animation-fill-mode: both;
}
@keyframes coruscate {
  0% {
    opacity: 0;
  }
  25% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  75% {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
.code-resend {
  color: #0072f5;
  font-size: 0.12rem;
}
.code-resend span {
  cursor: pointer;
}
.code-dark {
  color: #8d9099;
  font-size: 0.12rem;
}
.code-dark span {
  cursor: default;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值