web-dev-qa-db-fra.com

Passer l'état du module vuex à vue-router pendant beforeEach

J'utilise VueJS conjointement avec vuex et vue-router. J'ai un module vuex qui fait une mutation dans son magasin et essaie de l'utiliser pour déterminer si un utilisateur est authentifié ou non.

Voici à quoi ressemble mon code dans la partie pertinente.

main.js

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

router.beforeEach((to, from, next) => {
    console.log(router.app) // prints a Vue$2 object
    console.log(router.app.$store) // undefined
    console.log(store.getters.isAuthenticated) // false
    ...
}

const app = new Vue({
  store,
  router,
  ...App
})

app.$mount('#app')

/ store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import core from './modules/core'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    core: core
  }
})

export default store

/ store/modules/core.js

import * as types from '../types'
import api from '../../api'
import router from '../../router'

const state = {
  token: null,
  user: null,
  authenticated: false
}

const mutations = {
  [types.LOGIN_SUCCESS] (state, payload) {
    console.log('mutate')
    state.token = payload.token
    state.user = payload.user
    state.authenticated = true
    router.go('/')
  }
}

const getters = {
  isAuthenticated: state => {
    return state.authenticated
  }
}

const actions = {
  [types.LOGIN] (context, payload) {
    api.getToken(payload).then(response => {
      context.commit(types.LOGIN_SUCCESS, response)
    })
  }
}

export default {
  state,
  mutations,
  actions,
  getters
}

Lorsque je passe par ma logique pour déclencher l'action LOGIN, je peux voir que la mutation s'est exécutée correctement et lorsque j'utilise l'extension Chrome pour afficher l'état vuex pour mon core module, l'état de user et authenticated a été correctement modifié.

QUESTION

Il semble que ce module n'a tout simplement pas été chargé au moment où le routeur fonctionne dans le .beforeEach boucle. Est-ce vrai?

Si oui, quelles sont d'autres suggestions sur la façon de gérer cette situation? Si non, que fais-je de mal?

15
The Brewmaster

console.log(store.state.core.authenticated) retourne faux car vous ne vous êtes pas encore connecté.

Dans votre code, vous ne conservez les informations utilisateur nulle part. Par exemple. en utilisant localstorage

Mêmes considérations:

  1. Ne pas utiliser router.app.$store, utilisez store que vous importez
  2. Dans votre LOGIN_SUCCESS mutation, stocker les informations de connexion et le jeton dans localstorage
  3. Dans votre hook beforeEach, vérifiez localstorage, s'il a été rempli avec un jeton, obtenez les informations utilisateur et appliquez la mutation. Sinon, appelez simplement la page de connexion

Quelque chose comme ça..

const mutations = {
  [types.LOGIN_SUCCESS] (state, payload) {
    state.token = payload.token
    state.user = payload.user
    state.authenticated = true
    localstorage.setItem('token', payload.token)
    localstorage.setItem('user', payload.user)
  }
}

const actions = {
  [types.LOGIN] (context, payload) {
    return api.getToken(payload).then(response => {
      context.commit(types.LOGIN_SUCCESS, response)
      return response
    })
  }
}

router.beforeEach((to, from, next) => {
    let user = localstorage.getItem('user')
    let token = localstorage.getItem('token')
    if (user && token) {
      store.commit(types.LOGIN_SUCCESS, {token, user})
      next()
    }
    else if (!store.getters.isAuthenticated) {
      store.dispatch(types.LOGIN).then(() => next())
    } else {
      next()
    }
}
4
ridermansb