Vue: 在输入 vue-router 之前无法访问 Pinia Store
Vue: Can't access Pinia Store in beforeEnter vue-router
我正在使用 Vue 3,包括 Composition API 以及 Pinia 作为状态管理。
在选项API中有一个方法beforeRouteEnter,它内置于组件本身。不幸的是,该方法在组合 API 中不存在。这里的代码,本来应该在 beforeRouteEnter 方法中,直接写入了 setup 方法。但是,这意味着首先加载和显示组件,然后执行代码,如果检查失败,则将组件重定向到错误页面,例如。
我的想法是在路由的 beforeEnter 方法中直接在路由配置中进行检查。但是,我无法访问 Pinia Store,它似乎尚未初始化,尽管它之前在 main.js.
中被调用过
控制台日志
Uncaught Error: []: getActivePinia was called with no active Pinia. Did you forget to install pinia?
const pinia = createPinia()
app.use(pinia)
This will fail in production.
Router.js
import { useProcessStore } from "@/store/process";
const routes: Array<RouteRecordRaw> = [
{
path: "/processes/:id",
name: "ProcessView",
component: loadView("ProcessView", "processes/"),
beforeEnter: () => {
const processStore = useProcessStore();
console.log(processStore);
},
children: [
{
path: "steer",
name: "ProcessSteer",
component: loadView("ProcessSteer", "processes/")
},
{
path: "approve/:code",
name: "ProcessApprove",
component: loadView("ProcessApprove", "processes/")
}
]
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
main.js
import { createApp } from "vue";
import "@/assets/bundle-bootstrap.css";
import App from "@/App.vue";
import { createPinia } from "pinia";
import router from "@/router";
import SvgIcon from "@/components/SvgIcon.vue";
const pinia = createPinia();
const app = createApp(App);
app.use(pinia);
app.use(router);
app.component("SvgIcon", SvgIcon);
router.isReady().then(() => {
app.mount("#app");
});
However, I don't have access to the Pinia Store, which doesn't seem to be initialized yet, although it is called before in the main.js
什么之前?在导入 router
模块后,使用 const pinia = createPinia();
创建 Pinia 实例 - 导入时,包括对 createRouter()
的调用在内的所有副作用都是执行。一旦创建了路由器,它就会开始它的初始导航(在客户端 - 在服务器上你需要用 router.push()
触发它) - 如果你碰巧在 URL 匹配路线与使用 Pinia 商店的守卫, useProcessStore()
发生在 Pinia 创建之前...
Using a store outside of a component
您有两个选择:
- 要么确保任何
useXXXStore()
调用发生 在 Pinia 创建 (createPinia()
) 并安装 (app.use(pinia)
)
- 或者您将 Pinia 实例传递到组件之外的任何
useXXXStore()
...
// store.js
import { createPinia } from "pinia";
const pinia = createPinia();
export default pinia;
// router.js
import pinia from "@/store.js";
import { useProcessStore } from "@/store/process";
const routes: Array<RouteRecordRaw> = [
{
path: "/processes/:id",
name: "ProcessView",
component: loadView("ProcessView", "processes/"),
beforeEnter: () => {
const processStore = useProcessStore(pinia ); // <-- passing Pinia instance directly
console.log(processStore);
},
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
// main.js
import { createApp } from "vue";
import App from "@/App.vue";
import store from "@/store.js";
import router from "@/router";
const app = createApp(App);
app.use(store);
app.use(router);
router.isReady().then(() => {
app.mount("#app");
});
你可以在definestore的第二个参数中传递方法:
store.js
export const useAppStore = defineStore('app', () => {
const state = reactive({
appName: 'App',
appLogo: ''
})
return {
...toRefs(state)
}
})
router.js
router.beforeEach((to, from, next) => {
const apppStore = useAppStore()
next()
})
我正在使用 Vue 3,包括 Composition API 以及 Pinia 作为状态管理。
在选项API中有一个方法beforeRouteEnter,它内置于组件本身。不幸的是,该方法在组合 API 中不存在。这里的代码,本来应该在 beforeRouteEnter 方法中,直接写入了 setup 方法。但是,这意味着首先加载和显示组件,然后执行代码,如果检查失败,则将组件重定向到错误页面,例如。
我的想法是在路由的 beforeEnter 方法中直接在路由配置中进行检查。但是,我无法访问 Pinia Store,它似乎尚未初始化,尽管它之前在 main.js.
中被调用过控制台日志
Uncaught Error: []: getActivePinia was called with no active Pinia. Did you forget to install pinia?
const pinia = createPinia()
app.use(pinia)
This will fail in production.
Router.js
import { useProcessStore } from "@/store/process";
const routes: Array<RouteRecordRaw> = [
{
path: "/processes/:id",
name: "ProcessView",
component: loadView("ProcessView", "processes/"),
beforeEnter: () => {
const processStore = useProcessStore();
console.log(processStore);
},
children: [
{
path: "steer",
name: "ProcessSteer",
component: loadView("ProcessSteer", "processes/")
},
{
path: "approve/:code",
name: "ProcessApprove",
component: loadView("ProcessApprove", "processes/")
}
]
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
main.js
import { createApp } from "vue";
import "@/assets/bundle-bootstrap.css";
import App from "@/App.vue";
import { createPinia } from "pinia";
import router from "@/router";
import SvgIcon from "@/components/SvgIcon.vue";
const pinia = createPinia();
const app = createApp(App);
app.use(pinia);
app.use(router);
app.component("SvgIcon", SvgIcon);
router.isReady().then(() => {
app.mount("#app");
});
However, I don't have access to the Pinia Store, which doesn't seem to be initialized yet, although it is called before in the main.js
什么之前?在导入 router
模块后,使用 const pinia = createPinia();
创建 Pinia 实例 - 导入时,包括对 createRouter()
的调用在内的所有副作用都是执行。一旦创建了路由器,它就会开始它的初始导航(在客户端 - 在服务器上你需要用 router.push()
触发它) - 如果你碰巧在 URL 匹配路线与使用 Pinia 商店的守卫, useProcessStore()
发生在 Pinia 创建之前...
Using a store outside of a component
您有两个选择:
- 要么确保任何
useXXXStore()
调用发生 在 Pinia 创建 (createPinia()
) 并安装 (app.use(pinia)
) - 或者您将 Pinia 实例传递到组件之外的任何
useXXXStore()
...
// store.js
import { createPinia } from "pinia";
const pinia = createPinia();
export default pinia;
// router.js
import pinia from "@/store.js";
import { useProcessStore } from "@/store/process";
const routes: Array<RouteRecordRaw> = [
{
path: "/processes/:id",
name: "ProcessView",
component: loadView("ProcessView", "processes/"),
beforeEnter: () => {
const processStore = useProcessStore(pinia ); // <-- passing Pinia instance directly
console.log(processStore);
},
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router;
// main.js
import { createApp } from "vue";
import App from "@/App.vue";
import store from "@/store.js";
import router from "@/router";
const app = createApp(App);
app.use(store);
app.use(router);
router.isReady().then(() => {
app.mount("#app");
});
你可以在definestore的第二个参数中传递方法:
store.js
export const useAppStore = defineStore('app', () => {
const state = reactive({
appName: 'App',
appLogo: ''
})
return {
...toRefs(state)
}
})
router.js
router.beforeEach((to, from, next) => {
const apppStore = useAppStore()
next()
})