倒计时

使用

使用背景:发送短信或者发送验证码时的多少秒倒数,定时执行多次轮询的请求

// 引入倒计时类(class)
import { BuildCountdown } from '@/constance/countdown.js'

// 再需要的地方实例化一个countdown 对象
let countdown = new BuildCountdown(option,callback)

`还有${countdown.count}秒`

参数说明

第一个参数 option ,是一个配置对象 Object 类型

  • option.count Number类型 需要倒数的数值 默认10
  • option.unit String类型 本次倒计时 数值的单位 默认 s,d(天)、h(小时)、m(分钟)、s(秒)、ms(毫秒)
  • option.awaitTime Number类型 倒计时的间隔时间 默认1

第二个参数 callback ,是到时间结束,即 conut为0时执行的函数

new BuildCountdown({count: 1000, unit: 'ms', awaitTime: 1},() => {})

实例属性说明

  • countdown.count 倒数变化的数值
  • countdown.day 倒计时剩余天数
  • countdown.hour 倒计时剩余小时数
  • countdown.minute倒计时剩余分钟数
  • countdown.seconds 倒计时剩余秒数
  • countdown.millisecond 倒计时剩余毫秒数

day、hour、minute、seconds、millisecond 这些属性是不能通过countdown对象遍历出来的

// vue 的 computed 计算属性 
computed:{
  tieme () {
    return `${this.countdown.hour}时${this.countdown.minute}分${this.countdown.seconds}秒${this.countdown.millisecond}毫秒`
  }
}

实例方法说明

  • countdown.suspend() 倒计时暂停
  • countdown.start() 倒计时暂停之后 开始执行
  • countdown.refreshTimer() 刷新倒计时 重新开始倒计时
  • countdown.removeTimer() 移除倒计时 不会执行回调函数
  • countdown.handleTimeEnd() 结束倒计时 会执行回调函数
// vue 的 beforeDestroy 离开页面时 清楚倒计时
beforeDestroy() {
  this.countdown.removeTimer && this.countdown.removeTimer()
}

源码

/**
 * @param {option} 毫秒数
 * @param { option.count } 倒数的数值  默认10
 * @param { option.unit } 倒数的数值的单位  d天 h小时 m分钟 s秒(默认) ms毫秒
 * @param { option.awaitTime } 倒计时间隔时间数值   也是根据单位来确定具体时间
 * @param {timeEndCallback} 倒计时结束回调
 * 
 */

 export class BuildCountdown {
  constructor (option, timeEndCallback) {
    let {count, rotate, awaitTime } = BuildCountdown.filterOption(option)
    this.count = count // 倒计时的数字
    this.rotate = rotate // 单位换算成毫秒的比例
    this.countValue= count // 倒计时的原始数字
    this.awaitTime = awaitTime // setTime 的间隔时间
    this.timeEndCallback = timeEndCallback
    this.setTimer()
  }
  timer = null

  static filterOption (option) {
    // 分别计算出 一天、一小时等几毫秒
    let dateMap = {
      d: 1000 * 60 * 60 * 24,
      h: 1000 * 60 * 60,
      m: 1000 * 60,
      s: 1000,
      ms: 1
    }
    option = {
      count: 10, 
      unit: 's',
      awaitTime: 1,
      ...option
    }
    let result = {
      count: option.count * 1,
      rotate: dateMap[option.unit] || 1000
    }
    result.awaitTime = (option.unit === 'ms' && option.awaitTime < 9) ? 9 : option.awaitTime
    return result
  }
	
  get inCountdown () {
    return !!this.timer
  }
  get day () {
    return this.filterString(Math.floor((this.rotate * this.count) / (1000 * 60 * 60 * 24)))
  }
  get hour () {
    return this.filterString(Math.floor((this.rotate * this.count) % (1000 * 60 * 60 * 24) / (1000 * 60 * 60)))
  }
  get minute () {
    return this.filterString(Math.floor((this.rotate * this.count) % (1000 * 60 * 60 * 24) % (1000 * 60 * 60) / (1000 * 60)))
  }
  get seconds () {
    return this.filterString(Math.floor((this.rotate * this.count) % (1000 * 60 * 60 * 24) % (1000 * 60 * 60) % (1000 * 60) / 1000))
  }
  get millisecond () {
    return this.filterString(Math.floor((this.rotate * this.count) % (1000 * 60 * 60 * 24) % (1000 * 60 * 60) % (1000 * 60) % 1000), 3)
  }

  // 创建定时器
  setTimer () {
    if (this.count <= 0) return
    this.timer = setInterval(() => {
      this.count = this.count - this.awaitTime
      if (this.count <= 0) return this.handleTimeEnd()
    }, this.awaitTime * this.rotate)
  }
  // 暂停
  suspend () {
    clearInterval(this.timer)
  }
  // 开始计时
  start () {
    this.removeTimer()
    this.setTimer()
  }
  // 刷新定时器
  refreshTimer () {
    this.removeTimer()
    this.count = this.countValue
    this.setTimer()
  }
  // 结束倒计时
  handleTimeEnd () {
    this.count = 0
    this.removeTimer()
    this.timeEndCallback && this.timeEndCallback()
  }
  // 移除倒计时
  removeTimer () {
    clearInterval(this.timer)
    this.timer = null
  }
  // 格式化数字
  filterString (value, num = 2) {
    return (value + '').padEnd(num, '0')
  }
 }

知识点

  • 设置对象的 get set 属性时, 该属性不可以被遍历,不可以通过 for in 或者 Object.keys() 获取
  • 30 % 24 计算还有多少小时 应该把天先减去, 30模24等于6 还剩1天6小时
  • 倒计时毫秒时 因为setTimeout或者setInterval 最小间隔时间在4毫秒左右,不能真正做到1毫秒执行一次,这里选择使用最低9秒执行一次,为什么要用9?因为9乘以0到9 最终的个位数0~9这十个数都会出现,倒计时减9时,这样最后一位0到9都会出现,看着会更真实。
  • 多个参数的默认值就使用对象,就可以不用关注参数的顺序,只填写我们想要的
    option = {
      count: 10, 
      unit: 's',
      awaitTime: 1,
      ...option
    }
posted @ 2021-10-23 21:43  雨天。我  阅读(155)  评论(0)    收藏  举报