如何让Vue3组件等待Vuex异步状态加载完成后再渲染?
问题分析与解决方案
你的核心问题是Vuex的getProjects动作没有等待所有异步流程完成就提前resolve,导致组件在状态加载完毕前就开始挂载。这是因为你混合使用了await和.then()链式调用,且没有等待selectProject的dispatch完成。
关键问题点
- 混合
await与.then()导致流程提前结束:await fetch(...)只会等待请求返回响应,但后续的.then()回调是独立执行的,getProjects动作会在fetch完成后立即resolve,而非等待所有.then()执行完毕。 - 未等待
selectProjectdispatch:在调用context.dispatch("selectProject")时没有加await,导致getProjects不会等待这个异步动作完成。
修正后的代码
1. 重构getProjects动作(使用纯async/await代替链式调用)
async getProjects(context: any, parms: any) { context.commit("loadingStatus", true, { root: true }); console.log("1"); try { // 等待请求响应 const response = await fetch(`${process.env.VUE_APP_API}/projects?`, { method: "get", headers: { Authorization: `Bearer ${localStorage.getItem("token")}`, }, }); console.log("2"); if (!response.ok) { throw new Error(response.status.toString()); } // 等待响应解析为JSON const data = await response.json(); context.commit("setProjects", { data }); console.log("3"); const activeProjectId = localStorage.getItem( `activeProjectId_${context.rootState.auth.operator.accountId}` ); // 等待selectProject动作完成 if (activeProjectId) { console.log("setting project to storage"); await context.dispatch("selectProject", { projectId: activeProjectId }); } else if (data.length > 0) { console.log("setting project to default"); await context.dispatch("selectProject", { projectId: data[0].id }); } context.commit("loadingStatus", false, { root: true }); } catch (error) { console.error("There was an error!", error); context.commit("loadingStatus", false, { root: true }); } },
2. 优化selectProject动作(移除不必要的await)
因为Vuex的commit是同步操作,无需加await:
async selectProject(context: any, parms: any) { console.log("4"); context.commit("loadingStatus", true, { root: true }); const pjt = context.state.projects.filter( (project: any) => project.id === parms.projectId ); if (pjt.length > 0) { console.log("Project found"); context.commit("setActiveProject", pjt[0]); } else if (context.state.projects.length > 0) { console.log("Project not found setting first on the list"); context.commit("setActiveProject", context.state.projects[0]); } else { context.commit("resetActiveProject"); } context.commit("loadingStatus", false, { root: true }); },
修复效果
现在组件的beforeCreate中的await this.$store.dispatch('projects/getProjects')会等待:
- 接口请求完成并解析数据
setProjectscommit执行selectProject动作完全执行完毕(包括打印"4")- 所有状态更新完成
组件会在所有日志(1→2→3→4)打印完毕后才开始挂载,确保状态准备就绪。
内容的提问来源于stack exchange,提问作者Luis Novo
相关产品推荐
相关产品推荐

