前端Vue自定义发送短信验证码弹框popup 实现剩余秒数计数 重发短信验证码, 请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13207
效果图如下:
实现代码如下:
# cc-codeDialog
#### 使用方法
```使用方法
<!-- show:是否显示弹框 phone:手机号 autoCountdown:自动时间秒数 len:短信验证码长度 @closeClick:关闭弹框 @confirmClick:确认事件 -->
<cc-codeDialog :show="show" phone="1900000000" :autoCountdown="true" :len="6" @closeClick="closeCodeDialog" @confirmClick="confirmClick"></cc-codeDialog>
```
#### HTML代码实现部分
```html
<template>
<view class="content">
<button @click="showCodeDialog" style="margin-top: 39px;">发送短信验证码 </button>
<!-- show:是否显示弹框 phone:手机号 autoCountdown:自动时间秒数 len:短信验证码长度 @closeClick:关闭弹框 @confirmClick:确认弹框 -->
<cc-codeDialog :show="show" phone="1900000000" :autoCountdown="true" :len="6" @closeClick="closeCodeDialog"
@confirmClick="confirmClick"></cc-codeDialog>
</view>
</template>
<script>
export default {
data() {
return {
show: false
}
},
methods: {
showCodeDialog(item) {
this.show = true;
},
closeCodeDialog(item) {
this.show = false;
},
confirmClick(result) {
console.log("result = " + JSON.stringify(result));
this.show = false;
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
background-color: aliceblue;
height: 100vh;
}
</style>
```
#### 组件实现代码
```组件实现代码
<template>
<view v-if="show" class="codedialog">
<view class="mask"></view>
<view class="dialog-view">
<text class="dialog-close" @click="closeDialog()"></text>
<view class="dialog-hd">
<view class="codedialog-maintitle">
<text>发送验证码</text>
</view>
<view v-if="phone!='' && phone !=null " class="codedialog-subtitle">
<text>已发送到手机号:{{phoneStr}}</text>
</view>
</view>
<view class="dialog-bd">
<view class="code-view">
<view v-for="(code,index) of codeAry" :key="index" class="code-item">{{code.val}}</view>
</view>
</view>
<view class="dialog-ft">
<view v-if="countdown==60" @click="resend" class="resend">重新发送</view>
<view v-if="countdown<60" class="countdown">{{countdown}}s</view>
</view>
<button style="margin-top: 20px; width: 88%;background-color: royalblue;color: white;"
@click="confirmClick">确定</button>
</view>
<view class="keyboard">
<view class="keyboard-line">
<view data-val="1" @click="bindKeyEvent" class="button-item">1</view>
<view data-val="2" @click="bindKeyEvent" class="button-item">2</view>
<view data-val="3" @click="bindKeyEvent" class="button-item">3</view>
</view>
<view class="keyboard-line">
<view data-val="4" @click="bindKeyEvent" class="button-item">4</view>
<view data-val="5" @click="bindKeyEvent" class="button-item">5</view>
<view data-val="6" @click="bindKeyEvent" class="button-item">6</view>
</view>
<view class="keyboard-line">
<view data-val="7" @click="bindKeyEvent" class="button-item">7</view>
<view data-val="8" @click="bindKeyEvent" class="button-item">8</view>
<view data-val="9" @click="bindKeyEvent" class="button-item">9</view>
</view>
<view class="keyboard-line">
<view data-val="clear" @click="bindKeyEvent" class="button-item">清空</view>
<view data-val="0" @click="bindKeyEvent" class="button-item">0</view>
<view data-val="delete" @click="bindKeyEvent" class="button-item">x</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false
},
autoCountdown: {
type: Boolean,
default: true
},
phone: {
type: String,
default: ""
},
len: {
type: Number,
default: 6
}
},
data() {
return {
codeAry: [{
"val": ""
}, {
"val": ""
}, {
"val": ""
}, {
"val": ""
},
{
"val": ""
},
{
"val": ""
}
],
currItem: 0,
countdown: 60,
cTimer: null,
callResult: {
type: 0,
code: ''
},
suspend: false
};
},
computed: {
phoneStr() {
return this.phone.substr(0, 3) + "****" + this.phone.substr(7);
}
},
watch: {
show: function() {
console.log(this.show)
if (this.show) {
if (!this.suspend) {
this.init();
}
} else {
if (!this.suspend) {
this.clearTimer();
}
this.clearCode();
}
}
},
methods: {
init: function() {
var codeAry = [];
for (var i = 0; i < this.len; i++) {
codeAry.push({
val: ""
})
}
this.codeAry = codeAry;
this.currItem = 0;
if (this.autoCountdown) {
this.startTimer();
}
},
bindKeyEvent: function(e) {
var _this = this;
var val = e.currentTarget.dataset.val;
switch (val) {
case "clear":
_this.clearCode();
break;
case "delete":
_this.deleteCode();
break;
default:
_this.inputVal(val);
break;
}
},
inputVal: function(val) {
if (this.currItem < this.len) {
this.codeAry[this.currItem].val = val;
this.currItem++;
}
if (this.currItem == this.len) {
this.execuCall(1);
}
},
clearCode: function() {
this.init();
},
deleteCode: function() {
if (this.currItem > 0) {
this.codeAry[this.currItem - 1].val = "";
this.currItem--;
}
},
closeDialog: function() {
this.execuCall(-1);
this.$emit("closeClick");
},
startTimer: function() {
var _this = this;
if (_this.cTimer == null) {
_this.cTimer = setInterval(function() {
_this.countdown--;
if (_this.countdown == 0) {
_this.clearTimer();
}
}, 1000)
}
},
clearTimer: function() {
var _this = this;
clearInterval(_this.cTimer);
_this.cTimer = null;
_this.countdown = 60;
},
getCodeValue: function() {
var codeStr = "";
this.codeAry.forEach(function(code) {
codeStr += code.val;
})
return codeStr;
},
execuCall: function(type) {
this.callResult.type = type;
if (type == 1) {
this.callResult.code = this.getCodeValue();
this.clearTimer();
} else {
this.suspend = true;
this.callResult.code = '';
}
this.$emit("change", this.callResult);
},
resend: function() {
var _this = this;
_this.callResult.code = '';
_this.callResult.type = 0;
// _this.callResult.resendCall = function() {
// }
_this.init();
_this.$emit("change", _this.callResult);
},
confirmClick() {
console.log("result = " + JSON.stringify(this.callResult));
if (this.callResult.code.length < 6) {
uni.showModal({
title: '温馨提示',
content: '输入短信验证码长度有误'
})
} else {
this.$emit("confirmClick", this.callResult);
}
}
}
}
</script>
<style scoped>
.button-item:active {
background: #d4d4d4;
}
.button-item+.button-item {
border-left: 0.1px solid #d4d4d4;
}
.button-item {
flex: 1;
padding: 14px 0px;
}
.keyboard-line+.keyboard-line {
border-top: 0.1px solid #d4d4d4;
}
.keyboard-line {
display: flex;
}
.keyboard {
background: #fff;
position: absolute;
z-index: 999;
width: 100%;
left: 0;
bottom: 0;
font-size: 17px;
}
.dialog-close {
color: #999;
height: 28px;
width: 28px;
font-size: 19px;
top: 5px;
left: 5px;
position: absolute;
}
.dialog-close:before {
content: "\2716";
}
.countdown {
color: #666;
font-size: 16px;
}
.resend {
color: #007aff;
font-size: 16px;
}
.dialog-ft {
margin-top: 10px;
}
.code-view {
display: flex;
text-align: center;
margin: 0 auto;
border-collapse: separate;
border-spacing: 10px 5px;
}
.code-item+.code-item {
margin-left: 5px;
}
.code-item {
flex: 1;
border-bottom: 1px solid #999;
padding-bottom: 2px;
height: 60upx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30upx;
}
.dialog-bd {
margin-top: 5px;
}
.codedialog-subtitle {
margin-top: 5px;
padding: 5px 0px;
font-size: 15px;
line-height: 1.4;
word-wrap: break-word;
word-break: break-all;
color: #999;
}
.dialog-view {
position: fixed;
z-index: 999;
width: 70%;
max-width: 300px;
top: 50%;
left: 50%;
transform: translate(-50%, -120%);
background-color: #fff;
text-align: center;
border-radius: 3px;
overflow: hidden;
padding: 20px 10px;
}
.mask {
position: fixed;
z-index: 999;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, .6);
}
.codedialog {
z-index: 999;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
box-sizing: border-box;
text-align: center;
}
</style>
```