如何在 Vuex 中设置定时器?
How to set timer in Vuex?
我刚开始学习 Vue 和 Vuex。我正在尝试设置一个倒数计时器,当它被点击时从 5 秒开始计时。逻辑已放在 Vuex 存储中用于状态管理,但我无法将计时器设置为 运行(它停留在 5 不变)。
在 parent (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>
关于计时器为何不触发的任何提示?
首先点击StartResetButton.vue按钮,函数应该执行如下。
@btn-click="$emit"('change-game-button') 应该先执行,这样 gameInActive 应该是 false。
必须执行 startCounter 操作。
使用 console.log 验证它是否按预期顺序运行。我看不到它是如何工作的,因为 post 没有 StartResetButton.vue 代码。
startCounter 动作然后执行计数器突变,如果函数正常执行,它将在 4 处停止,因为计数器突变只执行一次。
我建议通过仅将 gameStartTimer 减 1 并在 startCounter 操作中的 gameStartTimer 值大于 0 时使用超时每 1 秒执行一次计数器突变来修改计数器突变。
问题是这不会执行点击处理程序:
@click="gameInActive? 'resetCounter' : 'startCounter'"
v-on
(@
) 值应该是用作事件处理程序的函数,或者是根据事件计算的表达式。此表达式不会导致 resetCounter
等函数调用,因为 typeof (this.gameInActive? 'resetCounter' : 'startCounter') === 'string'
。最好提供一个单一的处理程序来做出决定,而不是将条件放入模板中。
Vuex 支持 promises,异步操作最好使用 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;
}
},
我刚开始学习 Vue 和 Vuex。我正在尝试设置一个倒数计时器,当它被点击时从 5 秒开始计时。逻辑已放在 Vuex 存储中用于状态管理,但我无法将计时器设置为 运行(它停留在 5 不变)。
在 parent (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>
关于计时器为何不触发的任何提示?
首先点击StartResetButton.vue按钮,函数应该执行如下。
@btn-click="$emit"('change-game-button') 应该先执行,这样 gameInActive 应该是 false。
必须执行 startCounter 操作。
使用 console.log 验证它是否按预期顺序运行。我看不到它是如何工作的,因为 post 没有 StartResetButton.vue 代码。
startCounter 动作然后执行计数器突变,如果函数正常执行,它将在 4 处停止,因为计数器突变只执行一次。
我建议通过仅将 gameStartTimer 减 1 并在 startCounter 操作中的 gameStartTimer 值大于 0 时使用超时每 1 秒执行一次计数器突变来修改计数器突变。
问题是这不会执行点击处理程序:
@click="gameInActive? 'resetCounter' : 'startCounter'"
v-on
(@
) 值应该是用作事件处理程序的函数,或者是根据事件计算的表达式。此表达式不会导致 resetCounter
等函数调用,因为 typeof (this.gameInActive? 'resetCounter' : 'startCounter') === 'string'
。最好提供一个单一的处理程序来做出决定,而不是将条件放入模板中。
Vuex 支持 promises,异步操作最好使用 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;
}
},