vue开发 输入短信验证码输入6位 或者4位
不使用插件情况下,效果图如下图所示

<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>
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,
focused: false,
count: "",
show: false,
timer: null,
}
}
watch: {
code: {
handler(newVal) {
this.code = newVal.replace(/[^\d]/g, "");
if (newVal.length > 5) {
this.$nextTick(() => {
document.styleSheets[0].addRule(
".animated::before",
"left: 62% !important;"
);
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() {
this.$refs && this.$refs.vcode.focus();
},
computed: {
codeArr() {
return this.code.split("");
},
cursorIndex() {
const len = this.code.length === 6 ? 5 : this.code.length;
return len;
},
},
methods: {
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"
) {
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;
}