You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue 3+Vuex秒表问题:如何从状态指定的初始时间(00:10.000)开始继续计时

解决Vuex秒表从初始时间开始计时的问题

这是因为你的当前计时逻辑完全基于timeBegan和stoppedDuration的时间差,没有把初始的00:10.000作为基准偏移量纳入计算——相当于你只计算了从点击Start到现在的流逝时间,而没有叠加初始的10秒。我们需要把初始时间转换成毫秒数,让计时从这个基准开始累加,具体修改如下:

第一步:添加时间解析函数与初始偏移量

首先在store/stopwatch/index.js开头新增一个辅助函数,用来把时间字符串(比如"00:10.000")转换成毫秒数,同时在state中添加存储初始偏移量的字段:

// 新增:解析时间字符串为毫秒数
function parseTimeToMs(timeStr) {
  const [minSecPart, msPart] = timeStr.split('.');
  const [minutes, seconds] = minSecPart.split(':');
  return parseInt(minutes) * 60 * 1000 + parseInt(seconds) * 1000 + parseInt(msPart);
}

export default { 
  state: { 
    time: "00:10.000", 
    // 新增:存储初始时间对应的毫秒数,作为计时基准偏移
    initialOffsetMs: parseTimeToMs("00:10.000"),
    timeBegan: null, 
    timeStopped: null, 
    stoppedDuration: 0, 
    started: null, 
    running: false, 
    temp: { 
      min: "0", 
      sec: "0", 
      ms: "0", 
      secondsPassed: 0 
    } 
  },
  // ... 其余代码后续贴完整修改版
}

第二步:修改计时核心逻辑

在clockRunning action中,我们需要把初始偏移量叠加到流逝时间上,这样最终显示的时间就是初始时间加上从Start开始的流逝时间:

async clockRunning({ state, commit, dispatch }) {
  let currentTime = new Date();
  // 计算从开始到现在的净流逝时间(扣除暂停时长)
  let elapsedSinceStart = new Date(
    currentTime - state.timeBegan - state.stoppedDuration
  );
  // 叠加初始偏移量,得到总计时毫秒数
  let totalElapsedMs = elapsedSinceStart.getTime() + state.initialOffsetMs;
  let totalElapsed = new Date(totalElapsedMs);

  // 从总计时中提取分、秒、毫秒
  let min = totalElapsed.getUTCMinutes();
  let sec = totalElapsed.getUTCSeconds();
  let ms = totalElapsed.getUTCMilliseconds();

  // 更新累计秒数(基于总计时)
  commit("newTemp", { key: "secondsPassed", value: parseInt(totalElapsedMs / 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;
  }
},

第三步:重置时恢复初始状态

修改reset mutation,确保重置后重新计算初始偏移量(如果后续修改初始time字符串,重置也能正确恢复):

reset(state) {
  state.running = false;
  clearInterval(state.started);
  state.stoppedDuration = 0;
  state.timeBegan = null;
  state.timeStopped = null;
  // 重置时恢复初始时间,并重新计算偏移量
  state.time = "00:10.000";
  state.initialOffsetMs = parseTimeToMs(state.time);
}

完整修改后的store代码

// 新增:解析时间字符串为毫秒数
function parseTimeToMs(timeStr) {
  const [minSecPart, msPart] = timeStr.split('.');
  const [minutes, seconds] = minSecPart.split(':');
  return parseInt(minutes) * 60 * 1000 + parseInt(seconds) * 1000 + parseInt(msPart);
}

export default { 
  state: { 
    time: "00:10.000", 
    // 新增:存储初始时间对应的毫秒数,作为计时基准偏移
    initialOffsetMs: parseTimeToMs("00:10.000"),
    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 elapsedSinceStart = new Date(
        currentTime - state.timeBegan - state.stoppedDuration
      );
      // 叠加初始偏移量,得到总计时毫秒数
      let totalElapsedMs = elapsedSinceStart.getTime() + state.initialOffsetMs;
      let totalElapsed = new Date(totalElapsedMs);

      let min = totalElapsed.getUTCMinutes(); 
      let sec = totalElapsed.getUTCSeconds(); 
      let ms = totalElapsed.getUTCMilliseconds(); 

      commit("newTemp", { key: "secondsPassed", value: parseInt(totalElapsedMs / 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";
      // 重置时重新计算初始偏移量
      state.initialOffsetMs = parseTimeToMs(state.time);
    } 
  }, 
  getters: {} 
};

这样修改后,当你点击Start按钮,秒表就会从00:10.000开始递增计时,暂停、重置功能也能正常工作。如果后续需要修改初始时间,只需要修改state中的time字符串即可,解析函数会自动转换成对应的毫秒偏移量。

内容的提问来源于stack exchange,提问作者Aras121

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:42:39