简体   繁体   English

不能在单个商店内使用 vue-router 和 pinia

[英]Can't use vue-router and pinia inside a single store

I am using pinia and vue-router 4.x,but i am having a problem using both of them in a store.我正在使用 pinia 和 vue-router 4.x,但我在商店中同时使用它们时遇到问题。 each works independently,but not together.每个人独立工作,但不一起工作。

If i use如果我使用

import router from '../router'

router will work but pinia is failed with error路由器可以工作,但 pinia 因错误而失败

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

@line let authStore = useAuthStore(pinia);

//here is axiosroot.ts //这里是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"},
  
});

When i import router from vue-routern useRouter is undefined当我从 vue-routern 导入路由器时, useRouter未定义

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

the error错误

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

// here is the remainning relavant code // 这是剩余的相关代码


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'})
   },
 },
});

Router has to be used as a plugin in pinia.路由器必须用作 pinia 中的插件。 I read this in the pinia.documentation https://pinia.vuejs.org/core-concepts/plugins.html我在 pinia.documentation https://pinia.vuejs.org/core-concepts/plugins.html中读到了这个

When adding external properties, class instances that come from other libraries, or simply things that are not reactive, you should wrap the object with markRaw() before passing it to pinia.添加外部属性时,来自其他库的 class 实例,或者只是非反应性的东西,您应该在将 object 传递给 pinia 之前用 markRaw() 包装它。 Here is an example adding the router to every store:这是一个将路由器添加到每个商店的示例:

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

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

This will add pinia to every store you create.这将为您创建的每个商店添加 pinia。 The config in main.ts is the same as for vue plugins. 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)

Now you can access router in your stores.现在您可以访问商店中的路由器。

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

I resolved that wrapping the store in a function:我解决了将商店包装在 function 中的问题:

/*** 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("/")
      },
    },
  })();
}

For anyone using quasar v2.对于使用类星体 v2 的任何人。 This worked for me这对我有用

in your /src/stores/index.js file, add the following在您的 /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)
})

Then in your src/stores/[yourStore].js file use然后在您的 src/stores/[yourStore].js 文件中使用

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

I was having trouble when trying to add the $router as suggested in the top answer尝试按照最佳答案中的建议添加 $router 时遇到问题

It should work if you declare const router = useRouter();如果您声明const router = useRouter();它应该可以工作inside your store action instead of at the top of the module.在您的商店操作中,而不是在模块的顶部。

It's the same for const store = useSomeStore() declarations. const store = useSomeStore()声明也是如此。 They can't be used at the module route, and are often used within component setup functions and store actions.它们不能在模块路由中使用,并且通常在组件setup功能和存储操作中使用。

You don't need to create a plugin, but if you're likely to be using the router across all your stores it still might be worth doing so as mentioned in this answer不需要创建插件,但如果您可能在所有商店中使用路由器,则仍然值得这样做,如本答案中所述

In main.js :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')

In your store push routes with:在您的商店推送路线:

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

For anyone using quasar Framework v2对于任何使用 quasar Framework v2 的人

Locate /src/stores/index.js file and edit by找到 /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 

in the Store file在存储文件中

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

It's very easy to use vue-router inside of pinia store if you write your pinia store like a composable function.如果您像可组合的 function 一样编写您的 pinia 商店,那么在 pinia 商店中使用 vue-router 非常容易。 These setup stores are easy to write if you are already familiar with the composition API.如果您已经熟悉组合 API,那么这些设置存储很容易编写。


  
  
        
            import {
              useRouter
            } from "vue-router";
            import {
              ref,
              computed
            } from "vue"
            import {
              defineStore
            } from "pinia";
        
            export const useAuthStore = defineStore('authStore', () => {
              const router = useRouter()
        
              // your states are just reactive variables
              const token = ref(localStorage.getItem('token'))
        
              // your getters are just computed properties
              const loginStatus = computed(() => {
                return token.value ? true : false
              })
        
              // your actions are just javascript functions
              const DELETE_TOKEN(payload) = () => {
                token.value = payload
              }
        
              const UPDATE_LOGIN_STATUS = (payload) => {
                loginStatus.value = payload;
              }
        
              const logOut(payload) {
                DELETE_TOKEN(null);
                UPDATE_LOGIN_STATUS(false);
                router.push({
                  name: 'Login'
                })
              }
        
              return {
                token,
                loginStatus,
                DELETE_TOKEN,
                UPDATE_LOGIN_STATUS,
                logOut
              }
        
            })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM