javascript - 如何在 Vuex 中设置计时器?
问题描述
我刚开始学习 Vue 和 Vuex。我正在尝试设置一个倒数计时器,当它被点击时,它从 5 秒开始计数。逻辑已放置在 Vuex 存储中以进行状态管理,但我无法让计时器运行(它卡在 5 不变)。
在父母(Home.vue)
<template>
<div class="home">
<Header
@change-game-button="changeGameButton"
:gameInActive="gameInActive"
:gameActive="gameActive"
/>
</div>
</template>
<script>
import Header from '../components/Header'
export default {
name: 'Home',
components: {
Header,
},
data() {
return {
gameInActive: true,
gameActive: false
}
},
methods: {
changeGameButton() {
console.log("Game button fired");
this.gameInActive = !this.gameInActive;
this.gameActive = !this.gameActive;
}
}
}
</script>
在组件(Header.vue)
<template>
<div class="header-container">
<StartResetButton
@btn-click="$emit('change-game-button')"
:buttonText="gameInActive ? 'Start' : 'Restart'"
:buttonColor="gameInActive ? '#90ee90' : '#FED8B1'"
@click="gameInActive? 'resetCounter' : 'startCounter'"
/>
</div>
<div class="initialInstruction" v-if="gameInActive">{{ initialInstruction }}</div>
<div class="gameStartTimer" v-if="gameActive">{{ gameStartTimer }}</div>
</template>
<script>
import StartResetButton from "./StartResetButton";
import { mapActions, mapMutations, mapState } from "vuex";
export default {
components: {
StartResetButton,
},
props: {
gameInActive: Boolean,
gameActive: Boolean,
},
computed: {
...mapState(["gameStartTimer", "initialInstruction"])
},
methods: {
// ...mapMutations(["countDown"]),
...mapActions(["startCounter", "resetCounter"])
},
emits: ['change-game-button']
};
</script>
在商店 (index.js)
import { createStore } from 'vuex'
export default createStore({
state: {
gameStartTimer: 5,
initialInstruction: "Press Start to Begin"
},
mutations: {
stopCounter(state) {
state.gameStartTimer = 5
},
counter(state) {
if (state.gameStartTimer > 0) {
setTimeout(() => {
state.gameStartTimer--;
}, 1000)
}
}
},
actions: {
startCounter(context) {
context.commit('counter')
},
resetCounter(context) {
context.commit('stopCounter')
}
},
modules: {
}
})
StartResetButton.vue
<template>
<button
class="btn"
@click="onClick()"
:style="{ background: buttonColor }">
{{ buttonText }}
</button>
</template>
<script>
export default {
name: "StartResetButton",
props: {
buttonText: String,
buttonColor: String,
},
methods: {
onClick() {
this.$emit('btn-click')
}
}
};
</script>
关于为什么计时器不会触发的任何提示?
解决方案
问题是这不会执行点击处理程序:
@click="gameInActive? 'resetCounter' : 'startCounter'"
v-on
( @
) value 应该是用作事件处理程序的函数,或者是对事件进行评估的表达式。此表达式不会导致resetCounter
, 等函数调用,因为typeof (this.gameInActive? 'resetCounter' : 'startCounter') === 'string'
. 最好提供一个单独的处理程序来做出决定,而不是将条件放入模板中。
Vuex 支持 Promise,最好使用 Promise 控制流进行异步操作。setTimeout
回调执行一次。如果它应该多次递减,setTimeout
则应在循环中使用await
,或setInterval
应改为使用。
突变是直接访问状态的同步且通常细粒度的函数。可以有称为decrementCount
,startCounter
等的。
state: {
count: 5,
counter: false
},
actions: {
async startCounter({ state }) {
state.counter = true;
while (state.count > 0 && state.counter) {
await new Promise(resolve => setTimeout(resolve, 1000));
if (state.counter)
state.count--;
}
state.counter = false;
},
resetCounter(context) {
state.count = 5;
state.counter = false;
}
},
推荐阅读
- ruby-on-rails - undefined method `first' for nil:NilClass on .each statement
- python - How to hover Image using Canvas ? TKinter
- c# - Special shape of Line starting and ending point in wpf C#
- jenkins - i am getting [0m[[0m[0minfo[0m] [0m[0m in jenkins console on building sbt jenkins pipeline project
- python - PermissionError: [Errno 1] Operation not permitted: 'file.txt' -> 'symlink.txt' while using os.symlink
- palantir-foundry - Slate writeback to Phonograph2 fails with Phonograph2:EditPayloadTooLarge
- android - Flutter - "Finished with error: The plugin assets_audio_player could not be built due to the issue above."
- firebase - Firebase Authentification and Flask
- ios - How to round Int with two digits using NSNumberFormatter?
- java - Appium: autoAcceptAlert doesn't work to allow access to all photos on IOS 14