• [更准确的倒计时功能]vue中使用web worker 实现倒计时


    首先,引入worker

    如果想知道为什么settimeout和setinterval倒计时不准确可以先百度了解一下event loop 再来阅读效果更好

    我的环境:

     "vue": "^2.6.11",
     "@vue/cli-plugin-babel": "~5.0.4",
     "@vue/cli-service": "~5.0.4",
    
    • 1
    • 2
    • 3

    引入worker我们需要如下配置

    yarn add worker-loader -D

    我的版本是"worker-loader": “^3.0.8”

    vue.config.js

      // 解决打包的时报错
      parallel: false,
      chainWebpack: (config) => {
        // set worker-loader
        config.module
          .rule('worker')
          .test(/\.worker\.js$/)
          .use('worker-loader')
          .loader('worker-loader')
          .options({
            inline: 'fallback',
            filename: 'workerName.[hash].worker.js',
          })
          .end();
        // 解决:worker 热更新问题
        config.module.rule('js').exclude.add(/\.worker\.js$/);
        // 删除splitChunks 请勿删除
        config.optimization.delete('splitChunks');
    
        config.plugin('define').tap((args) => {
          const [define] = args;
    
          Object.assign(define, {
            IS_APPLET: JSON.stringify(true),
            UNIQUE_MARK: JSON.stringify(uniqueMark),
          });
          return args;
        });
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    好,引入工作已经完成了,其次我们需要新建一个worker文件先写一个onmessage测试

    使用worker

    ***.worker.js

    
    // 创建存放数据的obj
    const countObj = {
      timer: null,
      examTime: -1,
      stopTimeStatus: false,
      setTimer(data) {
        this.timer = data;
      },
      setExamTime(data) {
        this.examTime = data;
      },
      setStopTimeStatus(data) {
        this.stopTimeStatus = data;
      },
    };
    
    function countDown(time) {
      countObj.examTime = time;
      if (countObj.timer) {
        return;
      }
      // 倒计时结束后传递出timeEnd的消息
      if (time === 0) {
        postMessage(['timeEnd', 0]);
        return;
      }
      countObj.timer = setTimeout(() => {
        countObj.timer = null;
        countObj.examTime--;
        // 传递给vue文件倒计时后的时间
        postMessage(['countDown', countObj.examTime]);
        countDown(countObj.examTime);
      }, 1000);
    }
    
    onmessage = function (e) {
      const {
        data: { type, data },
      } = e;
      console.log('收到消息了', e);
      countDown(data);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    为了操作方便,我写了一个专门管理worker交互的js文件

    ***.js

    import Worker from './***.worker.js';
    
    const worker = new Worker();
    
    // 初始化
    export function init() {
      worker.postMessage({
        type: 'init',
        data: 'test',
      });
    }
    
    // 获取worker
    export function getWorker () {
      return worker;
    }
    
    //...还有一些方法就不细展示了, 都是关于时间的操作
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    如上面代码块,postMessage是向worker线程传递信息,然后可以被worker.js中的onmessage获取到。

    %重点%

    worker的引入方式

    import Worker from './***.worker';
    
    const worker = new Worker();
    
    • 1
    • 2
    • 3

    在我们配置好worker-loader之后可以使用这样的方式进行构造worker

    在vue文件中使用worker接收消息处理逻辑

    ***.vue

    // 引入刚才写的引入worker的js文件
    import * as countDownInstance from '../utils/***.js';
    
    // 创建worker并传入初始时间
    countDownInstance.startCount(this.time);
    const worker = countDownInstance.getWorker();
    worker.onmessage = (event) => {
      // 做你想要的操作  
      const { data } = event;
      const [type, time] = data;
        if (type === 'countDown') {
          this.time= time;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    最后我整理了互相调用的逻辑图方便理解

    请添加图片描述

  • 相关阅读:
    Python 中的省略号对象
    Springboot+Vue项目-基于Java+MySQL的图书馆管理系统(附源码+演示视频+LW)
    【mitmproxy 用法】
    k8s分布式图床(k8s,metricsapi,vue3+ts)
    解释Java中的安全模型
    万物皆可集成系列:低代码对接Web Service接口
    kubernetes集群安装实战
    C++ 常量
    vue本地开发设置代理连接本地后台服务
    《十》Qt各种对话框之QFontDialog
  • 原文地址:https://blog.csdn.net/AzeShinja/article/details/125413693