错误原因
vue3中main.ts初始化方式跟vue2不同,在vue3中可以自由调整use的加载顺序,vue2中使用pinia却不能使用Vue.use(pinia)来进行初始化,导致我在router.beforeEach中要使用到pinia的store就会报错:
Uncaught Error: 【🍍】: getActivePinia was called with no active Pinia. Did you forget to install pinia?
错误写法
无关代码已省略
main.ts
import {router} from './router';//这里router初始化时就已经调用了beforeEach
import pinia from './lib/utils/pinia'//这里包含了createPinia
import {PiniaVuePlugin} from 'pinia'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI);
Vue.use(PiniaVuePlugin);
new Vue({
pinia,
store,
router,
vuetify,
render: (h) => h(App),
}).$mount('#app');
router.ts
import {useAuthenticationStore} from "@/store/authentication";//这里是store的定义
router = new VueRouter({
mode: 'history',
routes: allRoutes,
});
router.beforeEach(async (to, from, next) => {
const token = useAuthenticationStore().token;
});
因为使用pinia的store早于new Vue({ pinia,…,于是报上面的错。
解决方案
原本想提前加载pinia,没有找到合适的方法。最终通过延迟调用router.beforeEach解决了。
解决的写法:
main.ts
import {_routers} from './router';
import pinia from './lib/utils/pinia'
import {PiniaVuePlugin} from 'pinia'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI);
Vue.use(PiniaVuePlugin);
const router = _routers.getRouter();
new Vue({
pinia,
store,
router,
vuetify,
render: (h) => h(App),
}).$mount('#app');
_routers.setBeforeEach();//解决的关键是这里,放在new Vue之后即可。
router.ts
import {useAuthenticationStore} from "@/store/authentication";
export class Routers {
private static instance = null;
private router;
private constructor() {
this.router = new VueRouter({
mode: 'history',
routes: allRoutes,
});
}
public static getInstance(): Routers {
if (this.instance == null)
this.instance = new Routers();
return this.instance;
}
public getRouter() {
return this.router;
}
public setBeforeEach(){
this.router.beforeEach(async (to, from, next) => {
const token = useAuthenticationStore().token;
});
}
}
export const _routers: Routers = Routers.getInstance();
补充
不知道为什么,发文章的时候上面的写法正常运行了,过了几个小时,在没有改动这部分代码的情况下,还是无法正常使用。是因为在new Vue之后的router.beforeEach()内的部分不会被执行,虽然不会报上面的错,但是整个路由守卫都失效了。
最终只能通过给router.beforeEach()增加setTimeOut解决了。