效果图
代码实现
< view> < view class = " tips" > 已发送验证码至< text class = " tips-phone" > {{ phoneNumber }}</ text> </ view> < view class = " code-input-wrap" > < input class = " code-input" v-model = " codeNumber" type = " number" :adjust-position = " false" :auto-blur = " true" maxlength = " 6" @input = " handleInputClick" /> < view class = " code-list" > < block v-for = " (item, index) in 6" :key = " index" > < view :class = " ['code-list-item', codeNumber.length == index ? 'active-item' : '']" > {{ codeNumber[index] }}</ view> </ block> </ view> </ view> < view class = " resending" v-if = " isSending" > {{ '重新发送(' + counter + 's)' }}</ view> < view class = " normal" v-else @click = " handleResend" > 重新发送</ view>
</ view>
data ( ) { return { phoneNumber : '' , codeNumber : '' , isPhoneValid : false , isCodeValid : false , isSending : false , timer : null , counter : 60 }
} ,
methods : { handleInputClick ( e ) { let val = e. detail. valuethis . codeNumber = valif ( val && val. length == 6 ) { this . isCodeValid = true } else { this . isCodeValid = false } } , sendSmsCode ( ) { if ( this . isPhoneValid) { if ( ! / ^1[3456789]\d{9}$ / . test ( this . phoneNumber) ) { uni. showToast ( { title : '手机号格式不正确' , icon : 'none' } ) return false } if ( ! this . isChecked) { this . showTips = true return false } } } , countDown ( ) { this . counter = 60 this . isSending = true this . timer = setInterval ( ( ) => { this . counter-- if ( this . counter < 0 ) { this . reset ( ) } } , 1000 ) } , reset ( ) { this . isSending = false if ( this . timer) { clearInterval ( this . timer) this . counter = 60 this . timer = null } } , handleResend ( ) { this . codeNumber = '' this . sendSmsCode ( ) }
}
.tips { font-size : 28rpx; font-weight : 400; line-height : 36rpx; .tips-phone { font-weight : bold; margin-left : 20rpx; }
} // 验证码输入
.code-input-wrap { margin : 40rpx 0; position : relative; height : 100rpx; .code-input { position : absolute; left : 0; top : 0; height : 100rpx; width : 100%; opacity : 0; z-index : 99; outline : none; } .code-list { position : absolute; left : 0; top : 0; width : 100%; height : 100rpx; display : flex; justify-content : space-between; .code-list-item { // flex : 1; width : 90rpx; height : 100rpx; background : #ffffff; border-radius : 16rpx; font-size : 36rpx; font-weight : 700; color : #adb3ba; line-height : 100rpx; text-align : center; margin-right : 10rpx; z-index : 5; box-sizing : border-box; } .code-list-item:last-child { margin-right : 0; } .active-item { border : 2rpx solid #ff466d; } }
}
.resending { font-size : 28rpx; font-weight : 500; line-height : 36rpx; margin-bottom : 60rpx; color : #a6acb2;
}
.normal { font-size : 28rpx; font-weight : 500; line-height : 36rpx; margin-bottom : 60rpx; color : #333;
}