「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
前端开发不可避免的,时不时的就会遇到产品要求实现一个倒计时的功能;除了样式上的不同,功能却基本都是一样的,那么将倒计时功能抽离出来,形成一个包或者库,是一件非常有意义的事。
这里会使用ts语法,并且基于 eventemitter3 库扩展,实现基于事件通知(on、emit)
几个功能点
关于倒计时库的设计:
- 倒计时应该可以通过 new 关键字去实例化
import { EventEmitter } from 'eventemitter3';
// 定义倒计时事件枚举
export enum CountdownEventName {
START = 'start',
STOP = 'stop',
RUNNING = 'running',
}
// 继承 EventEmitter,拥有 on、emit等方法
export class Countdown extends EventEmitter<CountdownEventMap> {
}
- 实例化的倒计时应该接受一个结束时间,还应该接受一个步数(每次跳动的间隔)
constructor(endTime: number, step: number = 1e3) {
super();
// 保存一下初始数据
this.endTime = endTime;
this.step = step;
}
- 实例化的倒计时应该有自己的状态
// 定义一些枚举
// 返回的数据格式
export interface RemainTimeData {
/** 天数 */
days: number;
/**
* 小时数
*/
hours: number;
/**
* 分钟数
*/
minutes: number;
/**
* 秒数
*/
seconds: number;
/**
* 毫秒数
*/
count: number;
}
// 状态枚举
enum CountdownStatus {
running,
paused,
stoped,
}
// 事件枚举
export enum CountdownEventName {
START = 'start',
STOP = 'stop',
RUNNING = 'running',
}
// 格式化方法 9 -> 09
export function fillZero(num: number) {
return `0${num}`.slice(-2);
}
-
实例化的倒计时应该在改变之后返回格式化的时间(days , hours , minutes , seconds)
-
实例化的倒计时应该提供开始和结束两个api
public start() {
// 丢出事件 倒计时开始
this.emit(CountdownEventName.START);
this.status = CountdownStatus.running;
// 倒计时方法
this.countdown();
}
public stop() {
// 丢出事件 倒计时停止
this.emit(CountdownEventName.STOP);
this.status = CountdownStatus.stoped;
}
关于库的打包:
-
最后构建完成的,应该是一个库,并且要在所有的模块定义下都可运行
-
应该可以根据当前 环境(
开发|生产)使用不同的文件(压缩|未压缩)
具体实现
主方法便携:倒计时的 countDown 方法其实很简单:
-
拿到结束时间 减去 现在的时间,得到剩余时间
-
判断剩余时间是否大于0:
大于0则将剩余时间格式化后,向外emit数据,然后更新剩余时间(减去step); -
重复第二步,直到倒计时小于或等于0,结束倒计时
webpack 打包构建:
-
可以使用 webpack 的
output.library配置项,将libraryTarget属性设置为umd,使之在所有的模块定义下都可运行; -
对于库来说,一般需要提供
min版本,和非压缩版本,可以在webpack中,配置两个入口,然后对于min版本的,使用terser-webpack-plugin插件进行压缩
完整版代码地址:countDownJs