vue3 pinia踩坑及解决方案详解
黑狼传说 人气:0安装
yarn add pinia # or npm install pinia
用法
// user.ts import { defineStore } from 'pinia' export const useUserStore = defineStore({ id: 'user', state: () => ({ ... }), actions: { ... } }) // components.vue import { useUserStore } from '@/store/user' const userStore = useUserStore()
使用中出现的问题
1、Cannot access 'useUserStore' before initialization
重现步骤
通常我们会在路由钩子中判断用户是否登陆,从而进行权限判断。如:
// permission.ts import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router' import router from './router' import { useUserStore } from './store/user' const userStore: any = useUserStore() router.beforeEach(async(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { // TODO 判断是否登录 if (userStore.name) { ... } }) // main.ts const app = createApp(App) app.use(createPinia()) import router from './router' import '@/permission' app.use(router) app.mount('#app')
问题原因
代码从上往下执行过程中,遇到const userStore: any = useUserStore()
,会进行用户状态模块的获取,但是应用还没有挂载,所以Pinia的全局状态还没有进行初始化。造成了初始化用户模块状态获取时,全局状态并没有初始化,所以造成了当前问题。
解决方案
在路由钩子函数进行用户状态模块的获取,调用路由钩子的时候,意味着全局状态已完全初始化完成。但会造成每次调用路由钩子都获取用户状态模块,会造成资源的浪费(当然可以达到预期目的,但并不是我们需要的)。我们可以在外层声明一个变量用来存储状态,在路由钩子中进行判断,如果当前变量为空,也就意味着状态还没有进行过获取,在当前情况下进行状态获取(类似于单例)。最终代码:
// permission.ts import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router' import router from './router' import { useUserStore } from './store/user' let userStore: any = null router.beforeEach(async(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { if (userStore === null) { userStore = useUserStore() } // TODO 判断是否登录 if (userStore.name) { ... } })
加载全部内容