You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 16:17:47