如何使用Vue js从状态时间开始秒表

Posted

技术标签:

【中文标题】如何使用Vue js从状态时间开始秒表【英文标题】:How to start stopwatch from state time using Vue js 【发布时间】:2021-11-29 03:01:42 【问题描述】:

我有一个使用 Vue 3 和 Vuex 的秒表代码,它具有可以启动、停止和重置的功能。

这是代码:

存储/秒表/index.js

export default 
  state: 
    time: "00:10.000",
    timeStarted: null,
    timeBegan: null,
    timeStopped: null,
    stoppedDuration: 0,
    started: null,
    running: false,
    temp: 
      min: "0",
      sec: "0",
      ms: "0",
      secondsPassed: 0
    
  ,
  actions: 
    start( state, commit, dispatch ) 
      if (state.running) return;
      if (state.timeBegan === null) 
        state.timeBegan = new Date();
      

      if (state.timeStopped !== null) 
        state.stoppedDuration += new Date() - state.timeStopped;
      

      commit("start", 
        callback: () => 
          dispatch("clockRunning");
        
      );
    ,
    async clockRunning( state, commit, dispatch ) 
      let currentTime = new Date();
      let timeElapsed = new Date(
        currentTime - state.timeBegan - state.stoppedDuration
      );
      let min = timeElapsed.getUTCMinutes();
      let sec = timeElapsed.getUTCSeconds();
      let ms = timeElapsed.getUTCMilliseconds();

      commit("newTemp", 
        key: "secondsPassed",
        value: parseInt(Math.abs((state.timeStarted - new Date()) / 1000), 10)
      );

      if (state.running) 
        await dispatch("zeroPrefix",  num: min, digit: 2 ).then(
          (zeroPrefixResponse) => 
            commit("newTemp", 
              key: "min",
              value: zeroPrefixResponse
            );
          
        );

        await dispatch("zeroPrefix",  num: sec, digit: 2 ).then(
          (zeroPrefixResponse) => 
            commit("newTemp", 
              key: "sec",
              value: zeroPrefixResponse
            );
          
        );

        await dispatch("zeroPrefix",  num: ms, digit: 3 ).then(
          (zeroPrefixResponse) => 
            commit("newTemp", 
              key: "ms",
              value: zeroPrefixResponse
            );
          
        );
        state.time =
          state.temp.min + ":" + state.temp.sec + "." + state.temp.ms;
      
    ,
    zeroPrefix(context, payload) 
      return new Promise((resolve) => 
        let zero = "";
        for (let i = 0; i < payload.digit; i++) 
          zero += "0";
        
        resolve((zero + payload.num).slice(-payload.digit));
      );
    
  ,
  mutations: 
    newTemp(state, payload) 
      state.temp[payload.key] = payload.value;
    ,
    addSecondPassed(state, second) 
      state.temp.secondsPassed += second;
    ,
    resetSecondPassed(state) 
      state.temp.secondsPassed = 0;
    ,
    start(state, payload) 
      state.started = setInterval(() => 
        payload.callback();
      , 10);
      state.running = true;
    ,
    stop(state) 
      state.running = false;
      state.timeStopped = new Date();
      clearInterval(state.started);
    ,
    reset(state) 
      state.running = false;
      clearInterval(state.started);
      state.stoppedDuration = 0;
      state.timeBegan = null;
      state.timeStopped = null;
      state.time = "00:10.000";
    
  ,
  getters: 
;

App.vue

<template>
  <div>
    <span class="time"> $store.state.stopwatch.time </span>
    <br />
    <button @click="start">Start</button>
    <button @click="stop">Stop</button>
    <button @click="reset">Reset</button>
  </div>
</template>

<script>
export default 
  methods: 
    start() 
      this.$store.dispatch("start");
    ,
    stop() 
      this.$store.commit("stop");
    ,
    reset() 
      this.$store.commit("reset");
    ,
  ,
;
</script>

这是codesandbox上的演示代码

上面的代码从 10 秒开始,然后单击开始按钮,秒从数字 0 开始,然后是 1、2、3。不要从 10 号继续。

如何从 10 秒的状态时间开始秒表?

所以当点击开始按钮时,秒数从 10 继续到 11、12、13 等等。

【问题讨论】:

【参考方案1】:

看起来问题是 10s 没有添加到 timeBegan。如果你减去 10 秒,它应该可以工作。

if (state.timeBegan === null) 
  state.timeBegan = new Date() - 10_000;

附带说明,突变应仅限于突变

此代码在突变中添加和删除间隔,与突变的工作方式背道而驰。

    start(state, payload) 
      state.started = setInterval(() => 
        payload.callback();
      , 10);
      state.running = true;
    ,
    stop(state) 
      state.running = false;
      state.timeStopped = new Date();
      clearInterval(state.started);
    ,

并且从突变中执行回调也不好。并不是说它不起作用,而是它创建了一个奇怪的状态流,违背了商店的工作原理。

【讨论】:

有没有办法使用state time: "00:10.000" 作为开始时间参考?不要使用号码10_000。因为我的需求会不时更改state time,并根据更改后的state time运行时间。所以我只需要setstatestate time中的state来更改初始时间,当秒表启动时,它将按照state中的set的初始时间运行。如果我必须使用10_000 之类的示例编号手动更改,我会感到困惑。我试过state.timeBegan = new Date() - state.time,但它不起作用 您也可以调整 state.stoppedDuration?‍♂️ 但 state.time 的值会被覆盖,因此这不是要更改的变量。

以上是关于如何使用Vue js从状态时间开始秒表的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js - Element UI - 如何知道表单验证的状态

如何使用 Vue.js + Vuex (createStore) 将“状态”变量保存到浏览器 localStorage

秒表的使用方法 秒表有几种计时方式

Vue.js 硬刷新后从输入中重置状态值。如何解决?

js中秒表无法使用清除间隔方法

如何将数据从 WYSIWYG 发送到数据库 (Vue.js)