Pinia 在从 Api Vue 路由器加载数据之前访问

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

我有一个使用 Pinia 构建的 Vue 3 应用程序,其中 App.vue 上有一些 Api 调用,需要在应用程序加载之前首先运行,并且所有内容都依赖于它,这是 api 调用之一负责获取当前登录用户的角色所以我正在获取角色并将其设置在 Pinia 商店中,这对于组件来说非常有用,但是当我尝试在 router.aftereach 事件中使用它时遇到问题,这里是代码

应用程序.vue

<script setup lang="ts">
import { RouterView } from 'vue-router'
import { refresh } from './api/user'
import { setAuthToken } from './api'
import { useOrgStore } from '@/stores/organization'
import { useUserStore } from '@/stores/user'
import { onMounted,ref } from 'vue';
import { getdevices } from '@/api/user'
import { getMembers, getOrganization,getUserMemberships } from '@/api/organization'


const org = useOrgStore()
const user = useUserStore()

let renderApp=ref(false)
onMounted(async() => {
  //refactor for vue 3
  
  //setting user data from vue 2
  let userdata = JSON.parse(localStorage.getItem("user")|| '{}')
  //user data is required for vue 3 to operate if it doesnt exist we redirect user to vue 2 probably the user is logged out
  // and acessing /v3 directly by save url
  if(Object.keys(userdata).length === 0){
    window.location.href = `${window.location.origin}/`
  }
  user.setUser(userdata)
  
  //setting activeBillingAccount from vue 2
  let userBillingInfo = JSON.parse(localStorage.getItem("user-active-billing-account")|| '{}')
  user.setActiveBillingAccount(userBillingInfo)

  try{
    if(user.user?.id){
      // devices
      await getdevices(user.user?.id).then(res => {
        user.setDevices(res.data)
      })
    }

    // get organization
    if (user.user?.id) {
      await getUserMemberships(user.user?.id).then(res => {
        org.setUserMembership(res.data)
      });
      
      if(org.userMembership?.length && org.userMembership?.length > 0){
        await getOrganization(org.userMembership?.[0].organizationID ?? '').then(res => {
        org.setOrganization(res.data)
      });
      }
    }
  
    if(org.organization?.id){
      //memberships
      const lastNameAscFilter = 'field=lastName&sort=ASC'
      await getMembers(org?.organization?.id, lastNameAscFilter).then(res => {
        if (res.data.memberships) {
          org.setMembers(res.data.memberships)
        }
      })
    }

  }catch(error){
    console.log("Error on App mounted")
  }
  renderApp.value=true
});

</script>

<template>
  <RouterView v-if="renderApp"/>
</template> 

当 api 调用返回响应时,商店会更新,并且它们是异步的,所以没有问题,这是路由器事件

路由器.ts

import { useOrgStore } from '@/stores/organization'

router.afterEach((to) => {
  const org = useOrgStore()
  console.log(org.organization) //returns null
})

现在,如果添加超时,它似乎起作用了,这意味着数据从 Api 调用中加载较晚,然后返回 null

router.afterEach((to) => {
setTimeout(() => {
  const org = useOrgStore()
  console.log(org.organization) //returns correct value
}, 2000);
})

main.ts

import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import vuetify from './plugins/vuetify'
import App from './App.vue'
import router from './router'
import i18n from './i18n'
import * as Sentry from "@sentry/vue";


const pinia = createPinia();
const app = createApp(App)
app.use(pinia)
app.use(vuetify)
app.use(i18n)
app.use(router)

app.mount('#app')

我确实尝试了link的解决方案,但不幸的是它对我不起作用,有什么帮助我的代码可能有问题吗?

vuejs3 vue-router pinia
1个回答
0
投票

只需将 router.afterEach 从 router.ts 移至 app.vue

import router from '@/router'
...
} catch (error) {
  console.log("Error on App mounted")
}
renderApp.value = true
router.afterEach((to) => {
  console.log(org.organization) //returns null
})

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