Невозможно использовать vue-router и pinia внутри одного магазина.

Я использую pinia и vue-router 4.x, но у меня возникла проблема с их использованием в магазине. каждый работает независимо, но не вместе.

если я использую

      import router from '../router'

маршрутизатор будет работать, но pinia не работает с ошибкой

      Uncaught ReferenceError: Cannot access 'useAuthStore' before initialization
at axiosroot.ts

@line let authStore = useAuthStore(pinia);

// здесь axiosroot.ts

      import axios from "axios";
import {useAuthStore} from '../stores/auth-store'
import { createPinia } from "pinia";
 const pinia=createPinia();
let authStore = useAuthStore(pinia);
const url = "http://127.0.0.1:8000/api";
const   myToken =authStore.getToken;
export default axios.create({
  url,
  headers:{"Accept":"application/json"},
  
});

Когда я импортирую маршрутизатор из vue-routern useRouter не определено

      import {useRouter} from 'vue-router'
const router =useRouter();

Ошибка

      Uncaught TypeError: Cannot read properties of undefined (reading 'push') 
--- 
error @ line router.push({name:'Login'})

// вот оставшийся соответствующий код

      
import { defineStore, acceptHMRUpdate } from "pinia";
//import router from '../router'
import {useRouter} from 'vue-router'
const router =useRouter();
export const useAuthStore = defineStore({
 id: "user",
 actions: {  
   LogOut(payload) {
     // this.DELETE_TOKEN(null);
     // this.UPDATE_LOGIN_STATUS(false);
     router.push({name:'Login'})
   },
 },
});

7 ответов

Роутер должен использоваться как плагин в pinia. Я прочитал это в документации pinia.documentation https://pinia.vuejs.org/core-concepts/plugins.html .

При добавлении внешних свойств, экземпляров классов из других библиотек или просто вещей, которые не являются реактивными, вы должны обернуть объект с помощью markRaw() перед передачей его в pinia. Вот пример добавления маршрутизатора в каждый магазин:

      // adapt this based on where your router is
import { router } from './router'

pinia.use(({ store }) => {
  store.router = markRaw(router)
})

Это добавит пинию в каждый созданный вами магазин. Конфигурация в main.ts такая же, как и для плагинов vue.

      import { createApp, markRaw } from 'vue';
import { createPinia } from 'pinia';
import App from './app/App.vue';
import { router } from './modules/router/router';

const app = createApp(App);
const pinia = createPinia();

pinia.use(({ store }) => {
  store.router = markRaw(router)
});
app.use(router)

Теперь вы можете получить доступ к роутеру в своих магазинах.

      export const useMyStore = defineStore("myStore", {
  state: () => {
    return {};
  },
  actions: {
    myAction() {
      router.push({ name: 'Home' }); 
  },
});

В main.js :

      import { createApp, markRaw } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const pinia = createPinia()
pinia.use(({ store }) => {
store.router = markRaw(router)
})
const app = createApp(App)

app.use(pinia)
app.use(router) 
app.mount('#app')

В вашем магазине проталкивайте маршруты с помощью:

      this.router.push({ name: 'home' });

Я решил, что обернуть хранилище в функцию:

      /*** THIS DOES NOT WORK ****/
const router = useRouter();

export const useLoginStore = defineStore("login", {
  state: () => ({
    loading: false,
    error: "",
  }),
  actions: {
    loginAction(credentials: AuthenticationRequest): Promise<void> {
      await login(credentials);
      router.replace("/")
    },
  },
});



/*** This actually works ***/
export default function useLoginStore() {
  const router = useRouter();

  return defineStore("login", {
    state: () => ({
      loading: false,
      error: "",
    }),
    actions: {
      loginAction(credentials: AuthenticationRequest): Promise<void> {
        await login(credentials);
        router.replace("/")
      },
    },
  })();
}

Для тех, кто использует quasar v2. Это сработало для меня

в файле /src/stores/index.js добавьте следующее

      import { markRaw } from 'vue'
import { route } from 'quasar/wrappers'

pinia.use(({ store }) => {
  // important! dont add a $router here
  store.router = markRaw(router)
})

Затем в вашем файле src/stores/[yourStore].js используйте

      this.router.push("/") // important! dont add a $router here

У меня возникли проблемы при попытке добавить $router, как это было предложено в верхнем ответе.

Для тех, кто использует quasar Framework v2

Найдите файл /src/stores/index.js и отредактируйте его

      import { useRouter } from 'vue-router' ---> import this

// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)
pinia.router = useRouter() ---> add this line 

в файле магазина

      this.router.push({ name: 'Home' }) --> use this

Если вам нужно использовать маршрутизатор в Pinia без передачи методов, реквизита или объекта, более чистым решением может быть следующее.

      import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const pinia = createPinia()

const app = createApp(App)
app.use(pinia)
app.use(router)
app.provide('router', router);
app.mount('#app')

И тогда в вашем магазине:

      import { inject } from "vue";
actions: {
    navigate() {
      const router = inject('router');
      router.push({
        name: "customers",
        params: { page: this.currentPage },
      });
    },
},

pinia.use() более гибок и позволяет передавать плагины, методы, объекты и реквизиты. Оба подходят для передачи маршрутизатора в Pinia.

Это должно работать, если вы объявите const router = useRouter();внутри действия вашего магазина, а не в верхней части модуля.

Это то же самое для const store = useSomeStore()декларации. Их нельзя использовать на маршруте модуля, и они часто используются внутри компонента. setupфункции и хранить действия.

Вам не нужно создавать плагин, но если вы, вероятно, будете использовать маршрутизатор во всех своих магазинах, возможно, это стоит сделать, как указано в этом ответе .

Другие вопросы по тегам