求助:Vue组件无法及时获取Vuex Store中的gameCards数组
问题:Vuex中gameCards无法在组件mounted时及时读取,且需复用避免重复请求
我的Vue应用里,gameCards集合存储在Vuex Store中。玩家输入游戏PIN码后,代码会校验PIN并获取对应gameCards存入Store,随后跳转到Memory组件。但在Memory组件的mounted钩子中读取gameCards时得到的是空数组,尽管浏览器开发者工具显示Store里已有数据。同时希望能在多组件复用gameCards,避免重复请求后端。
相关代码
1. PIN校验代码
checkPinExists(){ //this.$store.dispatch('retrieveGameByPin', this.enteredPin) this.retrieveGameByPin(this.enteredPin) .then(res => { this.fetchGameCards(this.currentGame.id); // 游戏存在时将对应卡片存入store this.currentGameError = false; // 到这里说明没有游戏错误 this.checked= true; if (this.currentGame.game_status === 'actief'){ this.$router.push("memory"); } }) .catch(err => { this.currentGameError = true; console.error(err); }); }
2. Vuex的fetchGameCards Action
export const fetchGameCards = ({commit}, game_id) => { return new Promise((resolve, reject) => { let status = ''; let data ={}; console.log("fetching gameCards "); fetch(`api/cardsByGame/${game_id}`) .then(async res => { status = res.status; if(status === 200) { data = await res.json(); } else { data =null; } }) .then(res=>{ if ( status === 200) { commit('SET_GAME_CARDS', data); resolve('GameKaarten gevonden'); } else { reject('Geen gamekaartenkaart beschikbaar'); } }); }); }
3. Memory组件代码片段
<script> import { mapState, mapActions } from 'vuex'; export default { mounted() { console.log("at mounted show GameCards:"), console.log(this.gameCards); this.createDeck(), this.createShowCards() }, computed: { ...mapState([ 'currentSpeler' ,'currentSpelerCard', 'currentGame', 'gameCards' ]), </script>
控制台输出
at mounted show GameCards: [Handler]]: Array(0) length: 0
解决方案
1. 修复跳转时机:等待fetchGameCards完成后再跳转
当前代码调用fetchGameCards后立刻执行$router.push,但fetchGameCards是异步操作,此时Store里的gameCards还未更新,导致Memory组件mounted时数据未就绪。修改checkPinExists,在fetchGameCards的异步流程完成后再跳转:
checkPinExists(){ this.retrieveGameByPin(this.enteredPin) .then(res => { // 等待fetchGameCards异步操作完成 return this.fetchGameCards(this.currentGame.id); }) .then(() => { this.currentGameError = false; this.checked= true; if (this.currentGame.game_status === 'actief'){ this.$router.push("memory"); } }) .catch(err => { this.currentGameError = true; console.error(err); }); }
2. 在Store中添加缓存逻辑,避免重复请求
修改fetchGameCards Action,先检查Store中是否已有对应游戏的gameCards,如果有直接返回,没有再请求后端。如果需要支持多游戏数据存储,建议将gameCards改为对象结构({ [gameId]: cardsArray }),方便快速判断:
export const fetchGameCards = ({commit, state}, game_id) => { // 若gameCards是对象结构,判断当前游戏的卡片是否已存在 if (state.gameCards[game_id]) { return Promise.resolve('GameKaarten al in store'); } // 若gameCards是数组,可结合currentGame判断是否已有当前游戏的有效数据 // if (state.gameCards.length > 0 && state.currentGame.id === game_id) { // return Promise.resolve('GameKaarten al in store'); // } return new Promise((resolve, reject) => { let status = ''; let data ={}; console.log("fetching gameCards "); fetch(`api/cardsByGame/${game_id}`) .then(async res => { status = res.status; if(status === 200) { data = await res.json(); } else { data =null; } }) .then(res=>{ if ( status === 200) { commit('SET_GAME_CARDS', { game_id, data }); // 若为对象结构,提交时需携带game_id // commit('SET_GAME_CARDS', data); // 数组结构则直接提交 resolve('GameKaarten gevonden'); } else { reject('Geen gamekaartenkaart beschikbaar'); } }); }); }
3. 在Memory组件中监听gameCards变化,确保数据就绪后初始化游戏
即使修复了跳转时机,也可以在组件中添加监听逻辑,保证数据更新后再执行游戏初始化,避免因异步延迟导致的问题:
export default { mounted() { this.initGameIfReady(); }, watch: { gameCards: { immediate: true, handler(newVal) { this.initGameIfReady(); } } }, methods: { initGameIfReady() { // 根据gameCards的结构调整判断条件 if (Array.isArray(this.gameCards) && this.gameCards.length > 0) { console.log("GameCards ready:", this.gameCards); this.createDeck(); this.createShowCards(); } } }, computed: { ...mapState([ 'currentSpeler' ,'currentSpelerCard', 'currentGame', 'gameCards' ]), }
通过以上步骤,既能保证Memory组件获取到完整的gameCards数据,又能实现多组件复用Store中的数据,避免重复请求后端。
内容的提问来源于stack exchange,提问作者M.Koops
相关产品推荐
相关产品推荐

