目标
实现一个倒计时
要点
ts的实际应用
Let's Go !!!
先来一个记录事件类型的枚举
export enum CountdownEventName {
START = 'start',
STOP = 'stop',
RUNNING = 'running',
}
再来一个记录执行状态的枚举
enum CountdownStatus {
running,
paused,
stoped,
}
来一个记录时分秒的interface
export interface RemainTimeDate {
days: number;
hours: number;
minutes: number;
seconds: number;
count: number;
}
由于使用了EventEmitter这个库记得引入一下
import { EventEmitter } from 'eventemitter3'
处理倒计时的主入口
interface CountdownEventMap {
[CountdownEventName.START] : [];
[CountdownEventName.STOP] : [];
[CountdownEventName.RUNNING] : [];
}
export class Countdown extends EventEmitter<CountdownEventMap> {
// 定义一下 天 时 分 秒 毫秒(跳动步数)
private static COUNT_IN_MILLSECOND: number = 1 * 100;
private static SECOND_IN_MILLSECOND: number = 10 * Countdown.COUNT_IN_MILLSECOND;
private static MINUTE_IN_MILLSECOND: number = 60 * Countdown.SECOND_IN_MILLSECOND;
private static HOUR_IN_MILLSECOND: number = 60 * Countdown.MINUTE_IN_MILLSECOND;
private static DAY_IN_MILLSECOND: number = 24 * Countdown.HOUR_IN_MILLSECOND;
private endTime: number; // 结束时间
private step: number; // 毫秒步数间隔
private remainTime: number = 0; // 倒计时剩余时间
private status: CountdownStatus = CountdownStatus.stoped; // 当前倒计时执行状态
constructor(endTime: number, step: number = 1e3) {
super() // 继承父类
this.endTime = endTime
this.step = step
}
}
再定义一下不同状态的执行函数
// 倒计时开始
public start() {
this.emit(CountdownEventName.START)
this.status = CountdownStatus.running
this.countdown()
}
// 倒计时结束
public stop() {
this.emit(CountdownEventName.STOP)
this.status = CountdownStatus.stoped
}
// 倒计时执行函数
private countdown() {
if (this.status !== CountdownStatus.running) {
return
}
this.remainTime = Math.max(this.endTime - Date.now(), 0)
this.emit(CountdownEventName.RUNNING, this.parseRemainTime(this.remainTime))
if (this.remainTime > 0) {
setTimeout(() => {
this.countdown()
}, this.step)
} else {
this.stop()
}
}
最后封装一个剩余时间的处理函数
// 很简单所以不加注释了,新手司机都可以看懂
private parseRemainTime(remainTime: number): RemainTimeDate {
let time = remainTime
const days = Math.floor(time / Countdown.DAY_IN_MILLSECOND)
time = time % Countdown.DAY_IN_MILLSECOND
const hours = Math.floor(time / Countdown.HOUR_IN_MILLSECOND)
time = time % Countdown.HOUR_IN_MILLSECOND
const minutes = Math.floor(time / Countdown.MINUTE_IN_MILLSECOND)
time = time % Countdown.MINUTE_IN_MILLSECOND
const seconds = Math.floor(time / Countdown.SECOND_IN_MILLSECOND)
time = time % Countdown.SECOND_IN_MILLSECOND
const count = Math.floor(time / Countdown.COUNT_IN_MILLSECOND)
return {
days,
hours,
minutes,
seconds,
count,
}
}
大功告成,我们去使用一下
const countdown = new Countdown(Date.now() + 60 * 60 * 1000, 1000)
countdown.on(CountdownEventName.RUNNING, remainTimeDate => {
const { hours, minutes, seconds, count } = remainTimeDate
// 定义一个变量接收然后展示到页面中,具体效果不在展示
let timeDisplay = [hours, minutes, seconds, count].map.join(':')
// 00:59:59:11
}
补充:
- 这么做的好处是什么?
- 首先可以实时的开启和停止倒计时
- stop的回调函数countdown.on(CountdownEventName.STOP, () => { // todo })