在 Vue 路由解析之前访问 Vuex

Posted

技术标签:

【中文标题】在 Vue 路由解析之前访问 Vuex【英文标题】:Access Vuex before Vue route is resolved 【发布时间】:2019-02-24 11:38:35 【问题描述】:

我有什么:

    具有需要身份验证的路由和公共路由的路由器 具有用户身份验证状态的 vuex

我想要什么:使用axios 向服务器发送请求以检查用户的身份验证状态应用加载之前(在路由器解析之前)。

router.js:

import Vue from 'vue'
import Router from 'vue-router'
import store from './store'

Vue.use(Router)

const router = new Router(
  ...
  routes: [
    
      path: '/',
      name: 'home',
      component: Home
    ,
    
      path: '/account',
      name: 'account',
      component: () => import(/* webpackChunkName: "account" */ './views/Account.vue'),
      meta: 
        requiresAuth: true
      
    
  ]
)

router.beforeEach((to, from, next) => 
  if (to.matched.some(route => route.meta.requiresAuth)) 
    if (store.state.authStatus)
      next()
    else
      next(name: 'home')
   else 
    next()
  
)

export default router

store.js:

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

const store = new Vuex.Store(
  state: 
    authStatus: false
  ,
  mutations: 
    setAuthStatus(state, authStatus) 
      state.authStatus = authStatus
    
  
)

 axios.get(...)
   .then(response => 
     store.commit('setAuthStatus', true)
   )

export default store

main.js:

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

new Vue(
  router,
  store,
  render: h => h(App)
).$mount('#app')

我的问题:当我在浏览器中输入mydomain.com/acount(之前未加载应用程序)同时获得授权时,无论如何我都会重定向到home。重定向后,我看到我已获得授权(我在 Home 组件中设置了一些 DOM 元素,仅对授权用户显示)。


我试过了,没有帮助:

store.js:

const store = new Vuex.Store(
  ...
  actions: 
    setAuthStatus(commit) 
      axios.get(...)
        .then(response => 
          commit('setAuthStatus', true)
        )
    
  
)

main.js:

store.dispatch('setAuthStatus').then(() => 
  new Vue(
    router,
    store,
    render: h => h(App)
  ).$mount('#app')
)

编辑:在main.js 我试图从

new Vue(
  router,
  store,
  render: h => h(App)
).$mount('#app')

new Vue(
  store,
  router,
  render: h => h(App)
).$mount('#app')

它也没有帮助。

【问题讨论】:

【参考方案1】:

绕过Vanojx1's answer,接下来我解决了我的问题。

store.js:

const store = new Vuex.Store(
  state: 
    authStatus: axios.get(...).then(response => 
      store.commit('setAuthStatus', true)
    ),
    userAuth: false
  ,
  mutations: 
    setAuthStatus(state, authStatus) 
      state.userAuth = authStatus
    
  
)

router.js:

router.beforeEach((to, from, next) => 
  if (to.matched.some(route => route.meta.requiresAuth)) 
    store.state.authStatus.then(() => 
      //we're getting 200 status code response here, so user is authorized
      //be sure that API you're consuming return correct status code when user is authorized
      next()
    ).catch(() => 
      //we're getting anything but not 200 status code response here, so user is not authorized
      next(name: 'home')
    )
   else 
    next()
  
)

【讨论】:

【参考方案2】:

在导航守卫中,你需要一些异步的东西,所以将你的 axios 承诺保存在商店中作为 authStatus。当它解决提交并设置登录状态时。 在导航守卫中等待 promise 被解析,然后调用 next 函数进入下一个路由器。

Store.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const store = new Vuex.Store(
  state: 
    /*  EXAMPLE
    authStatus: new Promise(resolve => 
      setTimeout(() => 
        const requestResult = true;
        store.commit("setAuthStatus", requestResult);
        resolve(requestResult);
      , 1000);
    ),
    */
    authStatus: axios.get(...).then((requestResult) => 
        store.commit("setAuthStatus", requestResult);
    ),
    loggedIn: false
  ,
  mutations: 
    setAuthStatus(state, loggedIn) 
      state.loggedIn = loggedIn;
    
  
);

export default store;

路由器.js

router.beforeEach((to, from, next) => 
  if (to.matched.some(route => route.meta.requiresAuth)) 
    store.state.authStatus.then(loggedIn => 
      if (loggedIn) next();
      else next( name: "home" );
    );
   else 
    next();
  
);

检查此解决方案是否有效here

【讨论】:

谢谢你的回答,但是axios调用的地方在哪里呢? requestResult 顺便说一下是一个对象(如果我们谈论 axios 响应) 好的,然后根据 axios 响应将 true 或 false 传递给提交【参考方案3】:

问题可能是由于输入网址时 https://example.com/account

它启动应用程序并且 axios 向服务器执行异步请求。 所以也许你应该尝试在 beforeEach 中进行 axios 调用。

通过这种方式,您可以毫无问题地验证用户身份。

问题是你不能让 axios 同步,所以你必须用 axios 返回一个 Promise 才能实现功能。

请告诉我这是否对您有任何帮助。

【讨论】:

以上是关于在 Vue 路由解析之前访问 Vuex的主要内容,如果未能解决你的问题,请参考以下文章

vue-router+vuex实现加载动态路由和菜单

如何在 Vuex 模块 Actions 中使用 vue-router?

Vue框架--Ruoyi解析(前端)

在 Vuex 商店中使用 vue-router

如何在 Vuejs 中测试受保护的路由保护的访问?

vue中实现刷新路由