手写一个基于事件通知倒计时的库

652 阅读2分钟

「这是我参与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,结束倒计时

countDown

webpack 打包构建

  • 可以使用 webpack 的 output.library配置项,将 libraryTarget 属性设置为 umd,使之在所有的模块定义下都可运行;

  • 对于库来说,一般需要提供 min 版本,和 非压缩 版本,可以在webpack中,配置两个入口,然后对于 min 版本的,使用 terser-webpack-plugin 插件进行压缩

完整版代码地址:countDownJs