我有一个秒表代码使用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等等。
看起来问题是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);
},
从突变中执行回调也是不好的。不是说它不能工作,而是它创建了一个奇怪的状态流,违背了商店的工作原理。