Доступ к Vuex до разрешения маршрута Vue - PullRequest
0 голосов
/ 20 сентября 2018

Что у меня есть:

  1. маршрутизатор с необходимыми для авторизации маршрутами и общими маршрутами
  2. 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.И после перенаправления я вижу, что я авторизован (я установил некоторый элемент DOM внутри компонента Home, который отображается только для авторизованных пользователей).


Я пробовал это, не помогло:

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

и это тоже не помогло.

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Проблема, вероятно, связана с тем, что при вводе URL https://example.com/account

запускается приложение, а axios выполняет асинхронный запрос к серверу.Поэтому, возможно, вам следует попытаться сделать вызов axios из beforeEach.

Таким образом, у вас не возникнет проблем с аутентификацией пользователя.

Дело в том, что вы не можете сделать axios синхронным, чтобы вы могличтобы получить функциональность, нужно вернуть обещание с помощью axios.

Скажите, пожалуйста, помогло ли это вам.

0 голосов
/ 22 сентября 2018

Обходя Ответ Vanojx1 , я решил свой вопрос следующим образом.

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()
  }
})
0 голосов
/ 20 сентября 2018

В навигационной панели вам нужно что-то асинхронное, поэтому сохраните свое обещание аксиоса в магазине как authStatus.Когда он решает зафиксировать и установить статус входа в систему.В навигационной панели дождитесь разрешения обещания и затем вызовите следующую функцию для входа в следующий маршрутизатор.

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;

router.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();
  }
});

Проверьте, работает ли это решение здесь

...