效果图
目录结构
关闭图标
dialog-vccode组件
dialog-vccode.js
Component({
properties: {
// 输入框的数量
inputLength: {
type: Number,
value: 4
},
// 单个输入框的宽度
inputWidth: {
type: String,
value: '58rpx'
},
inputHeight: {
type: String,
value: '58rpx'
},
// 是否显示输入的值,默认隐藏
showValue: {
type: Boolean,
value: false
},
//提示文字
tipText: {
type: String,
value: '请输入验证码'
},
//手机号码
phone: {
type: String,
value: ''
},
//手机号码提示
phoneTip: {
type: String,
value: '已发送到:'
},
//是否显示倒计时
showMask:{
type:Boolean,
value:false
},
//倒计时
countDown:{
type:Number,
value:5
},
//是否已发送验证码
alreadySend:{
type:Boolean,
value:false
}
},
data: {
// input是否获取焦点
inputFocus: true,
// 初始input值为空
currentValue: '',
},
methods: {
//请稍后再试
pleaseWait:function(){
wx.showToast({
title: '请稍后再试',
})
},
//重新发送验证码
reSendCode:function(){
this.triggerEvent('reSendCode',{value:true})
},
closeMask: function () {
this.setData({ showMask: false,currentValue:'' })
this.triggerEvent('closeMask',{value:false},{bubbles:true,composed:true})
},
showView({ phone }) {
var mPhone = phone.substr(0, 3) + '****' + phone.substr(7);
this.setData({
phone: mPhone,
})
},
// 设置当前的值
_setCurrentValue(e) {
// 在此处判断满6(inputLength)位,把值返回给上级父组件或页面
let currentValue = e.detail.value
// 改变时,派发一个事件,如果父组件或页面中需要实时获取改变后的值,可以监听这个事件。
this.triggerEvent('change', e.detail.value)
this.setData({
currentValue
})
if (currentValue.length >= this.data.inputLength) {
this._complate()
return
}
},
// 点击伪装的input时,让隐藏的input获得焦点
_focusInput() {
this.setData({
inputFocus: true
})
console.log(this.data.inputFocus)
},
_complate() {
this.triggerEvent('inputComplate', this.data.currentValue)
},
// 提供给外部调用的方法,显示/隐藏密码。接收一个参数,可以显性修改展示的状态。
toggleValue(state) {
this.setData({
showValue: state != undefined ? state : !this.data.showValue
})
},
// 清除input当前的值
clearCurrentValue() {
this.setData({
currentValue: ''
})
},
//确认按钮
tapConfirm() {
let value = this.data.currentValue
if (value.length < this.data.inputLength) {
return
}
this.triggerEvent('confirm', value)
this.closeMask()
},
},
ready: function (e) {
var phone = this.data.phone;
this.setData({
phone: phone.substr(0, 3) + '****' + phone.substr(7)
})
}
})
dialog-vccode.json
{
"component": true
}
dialog-vccode.wxml
{{tipText}}
{{phoneTip}}{{phone}}
{{currentValue.length>=index+1?currentValue[index]:''}}
重新发送({{countDown}}s)
重新发送
确定
dialog-vccode.wxss
.password-box .password-wrapper {
margin-top: 20rpx;
display: flex;
justify-content: center;
align-items: center;
}
.password-box .password-item {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.password-box .password-item::after {
display: block;
content: '';
position: absolute;
top: 0;
left: 0;
border: 1px solid #D8D8D8;
box-sizing: border-box;
width: 200%;
height: 200%;
border-radius: 4rpx;
transform: scale(0.5);
transform-origin: left top;
}
.password-box .password-item + .password-item {
margin-left: 44rpx;
}
.password-box .password-wrapper .hidden {
width: 14rpx;
height: 14rpx;
border-radius: 50%;
background: #999;
}
.password-box .password-wrapper .show {
color: #1a88f9;
}
.password-box .hidden-input {
width: 1px;
height: 0;
min-height: 0;
}
.mask{
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
background: rgba(0, 0, 0, 0.4);
height: 100vh;
width: 100vw;
z-index: 1000;
}
.set-password {
position: absolute;
top:35vh;
display: flex;
flex-direction: column;
align-items: center;
width: 540rpx;
padding-bottom: 20rpx;
height: auto;
background: #ffffff;
border-radius: 10rpx;
}
.tip {
position: relative;
top: -80rpx;
text-align: center;
height: 43rpx;
font-size: 32rpx;
font-family: MicrosoftYaHeiSemibold;
font-weight: 800;
text-align: center;
color: #333333;
line-height: 43rpx;
}
.close_view_reverse{
width:100%;
display: flex;
flex-direction: row-reverse;
}
.close_view{
display: flex;
flex-direction: row-reverse;
height: 100rpx;
width: 100rpx;
padding:10rpx 10rpx 0 0;
}
.divider_line{
position: relative;
top:-20rpx;
width: 540rpx;
height: 1px;
background-color: #f0f1f1;
}
.btn-next {
background: #1a88f9;
border-radius: 110rpx;
box-shadow: 0px 4rpx 10rpx 0rpx rgba(0,0,0,0.1);
box-sizing: border-box;
margin: 0 auto 0;
width: 260rpx;
height: 70rpx;
line-height: 70rpx;
text-align: center;
color: #fff;
background: #d8d8d8;
}
.btn-next-active {
background: #1A88F9;
}
.verify-content{
position: relative;
top: -70rpx;
text-align: center;
height: 30rpx;
font-size: 24rpx;
color: #C5C5C5;
}
.text_countDown{
position: relative;
top: -50rpx;
height: 30rpx;
font-size: 22rpx;
text-decoration: underline;
text-align: center;
color: #999999;
line-height: 30rpx;
}
.c_flex{
display: flex;
align-items:center;
}
index中调用组件
index.wxml
点击获取验证码
index.json
{
"usingComponents": {
"dialog-vccode":"/component/dialog-vccode/dialog-vccode"
}
}
index.js
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
showMask: false,
countDown: 60,//倒计时时间s
alreadySend: false,//验证码是否发送
clearInterval: false,//释放interval重置倒计时
currentTimeStamp: 0,
isDown: true,
},
onLoad: function () {
},
onShow: function () {
this.dialogVCode = this.selectComponent('#dialogVCode')
},
//显示验证码提示框
getVCode: function () {
//防止快速点击
let intervalTimeStamp=Date.now() - this.data.currentTimeStamp;
if (this.data.currentTimeStamp&&intervalTimeStamp<=1000) {
console.log('点击获取验证码按钮时当前时间戳', this.data.currentTimeStamp)
console.log('点击间隔时间:', intervalTimeStamp+'毫秒')
wx.showToast({
title: '点击的太快了',
})
return
}
this.setData({
currentTimeStamp: Date.now()
})
console.log('点击获取验证码按钮时当前时间戳', this.data.currentTimeStamp)
console.log('点击间隔时间:', intervalTimeStamp+'毫秒')
//显示验证码框
this.setData({
showMask: true,
countDown: 60,
alreadySend: true,
clearInterval: false
})
//开启倒计时
this.timer()
//传入手机号码
this.dialogVCode.showView({ phone: '18855556666' })
},
//验证码倒计时
timer: function () {
if (!this.data.showMask) return
let promise = new Promise((resolve, reject) => {
let setTimer = setInterval(
() => {
this.setData({
countDown: --this.data.countDown
})
if (this.data.countDown <= 0) {
this.setData({
countDown: 60,
alreadySend: false
})
resolve(setTimer)
} else {
//关闭验证码框后重新点击按钮时,释放上一个正在执行的setInterval
if (this.data.clearInterval) {
resolve(setTimer)
}
}
}, 1000)
})
promise.then((setTimer) => {
clearInterval(setTimer)
})
},
//重新发送
reSendCode: function (e) {
console.log('重新发送验证码', e.detail.value)
wx.showToast({
title: '验证码已发送',
})
this.setData({
alreadySend: e.detail.value,
countDown: 60
})
this.timer()
//调用发送验证码接口
},
//自定义验证码弹框的确定
verifyCodeConfirm(e) {
console.log('验证码弹框的确定', e.detail)
//确定后重新计时
this.setData({
countDown: 60,
clearInterval: true,
alreadySend: false
})
},
//关闭验证码提示框
closeMask: function (e) {
console.log('验证码关闭按钮', e.detail.value)
this.setData({
showMask: e.detail.value,
clearInterval: true
})
},
})
index.wxss
.c_flex_center{
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
如果本篇文章能帮到您,那真是非常荣幸!