- A+
所属分类:Web前端
前端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代码实现部分
<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>