我无法从 Pinia Vuejs3 商店访问我的路线

问题描述 投票:0回答:4

我无法从商店访问我的路线。 对此或许有一个很好的解释。 我使用 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 方法那样执行控制台日志时

我有一个未定义的

javascript vue-router vuejs3 pinia
4个回答
7
投票

编辑:感谢sophiews指出这一点。

刚刚发现我们有不同的方式来定义Store:Setup Stores

// 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')

然后

router
api
可以在
this

上使用
// 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
}

对于打字稿用户,要正确获取
this.router
this.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
  }
}

我在 pinia github 上找到了这种方法。 https://github.com/vuejs/pinia/discussions/1092

但我还是不知道如何将

this.route
添加到Pinia。

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


3
投票

useRoute
useRouter
必须在 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
})

1
投票

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

    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(),
)();


0
投票

回答如何访问 pinia 存储中的

route
(如果它采用选项存储语法),因为它没有真正得到回答,特别是@ChristhoferNatalius

您似乎可以将路由作为插件添加到 pinia 商店,就像将路由器添加为插件一样。

// main.js
import { useRoute } from 'vue-router'

const pinia = createPinia();
pinia.use(({ store }) => {
  store.route = useRoute();
})

app.use(pinia);

// inside your store...
const store = defineStore('myStore', {
  state: () => ({ ... })
  actions: {
    mapUrlQueryParamsToFilters() {
      console.log('route', this.route); // entire route object is here
    }
  }
})

我不确定它是否完全正确,但我似乎能够很好地访问路由对象...我在 Pinia 的 Github 讨论上创建了一个线程,以便人们可以告诉我我是否错了哈哈...

https://github.com/vuejs/pinia/discussions/2732

© www.soinside.com 2019 - 2024. All rights reserved.