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
相关产品推荐
相关产品推荐

