<template> <view class="tn-code-class tn-code"> </view> </template> <script> export default { name: 'tn-verification-code', props: { // 倒计时总秒数 seconds: { type: Number, default: 60 }, // 开始时提示文字 startText: { type: String, default: '获取验证码' }, // 倒计时提示文字 countDownText: { type: String, default: 's秒后重新获取' }, // 结束时提示文字 endText: { type: String, default: '重新获取' }, // 是否在H5刷新或各端返回再进入时继续倒计时 keepRunning: { type: Boolean, default: false }, // 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了 uniqueKey: { type: String, default: '' } }, data() { return { timer: null, secNum: this.seconds, // 是否可以执行验证码操作 canGetCode: true } }, watch: { seconds: { handler(n) { this.secNum = n }, immediate: true } }, mounted() { this.checkKeepRunning() }, beforeDestroy() { this.setTimeToStorage() if (this.timer) { clearInterval(this.timer) this.timer = null } }, methods: { // 检查是否继续运行 checkKeepRunning() { // 获取上一次退出页面时的时间戳,如果没有上次保存,该值为空 let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$tCountDownTimestamp')) if (!lastTimestamp) return this.changeEvent(this.startText) // 当前秒的时间戳 // + new Date() 相当于 new Date().getTime() let nowTimestamp = Math.floor((+ new Date()) / 1000) // 判断当前的时间戳,是否小于上一次的设定结束的时间,提前于结束的时间戳 if (this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) { // 剩余尚未执行完倒计时秒数 this.secNum = lastTimestamp - nowTimestamp // 清除本地保存的变量 uni.removeStorageSync(this.uniqueKey + '_$tCountDownTimestamp') // 开始倒计时 this.start() } else { // 如果不存在需要继续上一次的倒计时,执行正常的逻辑 this.changeEvent(this.startText); } }, // 开始倒计时 start() { // 防止快速点击获取验证码按钮导致产生多个定时器导致混乱 if (this.timer) { clearInterval(this.timer) this.timer = null } this.$emit('start') this.canGetCode = false this.changeEvent(this.countDownText.replace(/s|S/, this.secNum)) this.setTimeToStorage() this.timer = setInterval(() => { if (--this.secNum) { this.changeEvent(this.countDownText.replace(/s|S/, this.secNum)) } else { // 倒计时结束,清空定时器、重置提示信息 this.reset() this.$emit('end') } }, 1000) }, // 重置倒计时 reset() { this.canGetCode = true if (this.timer) { clearInterval(this.timer) this.timer = null } this.secNum = this.seconds this.changeEvent(this.endText) }, // 倒计时改变事件 changeEvent(text) { this.$emit('change', text) }, // 保存当前时间戳 // 防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来 setTimeToStorage() { if (!this.keepRunning ||!this.timer) return // 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时 // 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理 if (this.secNum > 0 && this.secNum <= this.seconds) { let nowTimestamp = Math.floor((+ new Date()) / 1000) // 保存本次倒计时结束时候的时间戳 uni.setStorageSync(this.uniqueKey + '_$tCountDownTimestamp', nowTimestamp + this.secNum) } } } } </script> <style lang="scss" scoped> .tn-code { width: 0; height: 0; position: fixed; z-index: -1; } </style>