我无法从商店访问我的路线 皮尼亚 Vuejs3



我无法从商店访问我的路线。对此可能有一个很好的解释。我使用Vuejs3和Pinia

我的商店:

import {defineStore} from 'pinia'
import {useRoute} from "vue-router";

type navigationState = {
selectedNavigationItem: INavigationItem | null,
selectedNavigationPage: INavigationPage | null,
}
export const useNavigationStore = defineStore('navigationStore', {
state: () => ({
/**
* when the user clicks on an element of the navbar we store the navigation item here
*/
selectedNavigationItem: null,
/**
* when the user clicks on an element of the sidebar we store the navigation page here
*/
selectedNavigationPage: null,
} as navigationState),
actions: {
/**
* Set Selected navigation page
* @param navigationPage
* @type INavigationPage
*/
setSelectedNavigationPage(navigationPage: INavigationPage | null) {
console.log(useRoute())
this.selectedNavigationPage = navigationPage
},
},
})

当我在方法setSelectedNavigationPage中执行控制台日志时

我有一个未定义的

编辑:感谢sophiews指出这一点

刚刚发现我们有不同的方法来定义商店:设置商店

// src/stores/user.js
import { defineStore } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import api from './api.js'
export const useUserStore = defineStore('User', () => { // use function
const route = useRoute()
const router = useRouter()

const login = async () => {
await api.POST('login', {username, password})
router.replace({name: 'home'})
}
return { login } // IMPORTANT: need to return anything we need to expose
})

老答案

你可以添加路由器作为Pinia插件

// src/main.js
import { createPinia } from 'pinia'
import { createApp, markRaw } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import Home from './views/HomePage.vue'
import Api from './api.js' // my axios wrapper
const app = createApp(App)
// I usually put this in a separate file src/router.js and export the router
const routes = [ 
{ path: '/', component: HomePage },
]
const router = createRouter({
history: createWebHistory(),
routes,
})
const pinia = createPinia()
pinia.use(({ store }) => {
store.router = markRaw(router)
store.api = markRaw(Api)
})
app
.use(pinia)
.use(router)
.mount('#app')

routerapithis上可用

// src/stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('User', {
state: () => ({}),
actions: {
async login() {
await this.api.POST('login', {username, password})
this.router.replace({name: 'home'})
}
}
})

请注意,不能使用箭头函数调用this.router

login: async () => {
this.router.replace({name: 'home'}) // error
}

对于typescript用户,要正确获取this.routerthis.api的类型:

// src/global.d.ts
import { Router } from 'vue-router'
import Api from './api'
export { }
declare global {
}
declare module 'pinia' {
export interface PiniaCustomProperties {
router: Router,
api: typeof Api
}
}

我在松树上找到了这条路。https://github.com/vuejs/pinia/discussions/1092

但我仍然不知道如何将this.route添加到Pinia中。

未来的读者,如果你知道如何做,请评论。

useRouteuseRouter必须用于Vue组件,特别是setup方法或script setup内部

使用路由器文档

使用路线文档


如果你想访问router,你可以简单地导入它:

路由器文件

import { createRouter, createWebHistory } from 'vue-router'
export const router = createRouter({
history: createWebHistory(),
routes: [/* ... */]
})

然后在你的pinia商店里,你可以导入并使用该文件中的路由器:

import { defineStore } from 'pinia'
import router from './router'
export const myStore = defineStore('myStore', () => {
// router.push
// router.replace
})

您可以在工厂/函数中封装实例化存储的过程,这将允许您根据自定义需求扩展存储功能。下面您可以看到,我们可以实例化一个引用urql客户端和router对象的存储。看看:

export class StoreManager {
static _instances: any[] = [];
public static spawnInstance(
id: string,
storeType?: EStoreType,
clientHandle?: ClientHandle,
routerHandle?: Router,
) {
if (StoreManager._instances.find((i) => i.id === id)) {
const store = StoreManager._instances.find((i) => i.id === id).instance;
return store;
} else {
const store = StoreManager.initStore(
id,
storeType,
clientHandle ?? null,
routerHandle ?? null,
);
StoreManager._instances.push({
id: id,
instance: store,
storeType: storeType,
});
return store;
}
}
public static initStore(
id: string,
storeType: EStoreType,
clientHandle: ClientHandle | null,
routerHandle: Router | null,
) {
const baseState = {
_meta: {        
storeType: storeType,
isLoading: true,        
},
_client: clientHandle,
_router: routerHandle,
};
const baseActions = {
async query(query: any, variables: any[] = []) {
// use urql client

},
};
const baseGetters = {
storeType: (state) => state._meta.storeType,
getCurrentRoute: (state) => {
if (!state._router) {
throw new RouterNotSetException(
`This store does not have a router set up`,
);
}
return state._router.currentRoute.fullPath.replace('/', '');
},
};
switch (storeType) {
case EStoreType.DEFAULT:
return defineStore({
id: `${id}`,
state: () => ({
...baseState,
}),
actions: {
...baseActions,
},
getters: {
...baseGetters,
},
});
default:
throw new StoreTypeNotFoundException(
`Expected valid 'EStoreType', got ${storeType}`,
);
}
}
}

在你的VueComponent中,一个商店实例会像这样产生:

const store = StoreManager.spawnInstance(
uuidv4(),
EStoreType.DEFAULT,
useClientHandle(),
useRouter(),
)();

最新更新