首页 > 解决方案 > 如何确保我的 vuex 商店在路由器中可用

问题描述

美好的一天,我正在开发一个同时使用 vue-router 和 vuex 的 vue 项目在应用程序中,只要登录成功,我就会将 JWT 令牌存储在 vuex 中。但是我正在努力解决以下问题

1) 在我的导航栏中动态显示/隐藏登录/注销按钮 2) 当 router.js 中的路由更改时访问 vuex 存储中的 JWT 令牌

所以基本上我需要访问我的路由器中的 vuex 存储,以及当我的 vuex 状态更改时(即登录成功时)如何更新我的导航栏组件

下面是我的代码。我将从main.js开始

import Vue from 'vue'
import Router from 'vue-router'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import App from '../app.vue'
import router from '../router.js'
import store from '../store'

Vue.use(Router)
Vue.use(Vuetify)

const vuetify = new Vuetify

document.addEventListener('DOMContentLoaded', () => {
  new Vue({
        el: '#app',
        router,
        vuetify,
        store,
        render: h => h(App)         
  })
})

然后router.js

import Router from 'vue-router'
import Index from './views/index.vue'
import Appointments from './views/appointments.vue'
import CreateAppointment from './views/createAppointment.vue'
import Login from './views/login.vue'
import store from './store'

const router =  new Router({
    routes: [
        {
            path: '/',
            name: 'root',
            component: Index
        },
        {
            path: '/login',
            name: 'login',
            component: Login
        },
        {
            path: '/index',
            name: 'index',
            component: Index
        },
        {
            path: '/appointments',
            name: 'appointments',
            component: Appointments,
            props: true,
            meta: { 
                requiresAuth: true
           }
        },
        {
            path: '/create-appointment',
            name: 'create-appointment',
            component: CreateAppointment,
            meta: { 
               requiresAuth: true
           }
        }
    ]
})   

router.beforeEach((to, from, next) => {
  if(to.matched.some(record => record.meta.requiresAuth)) {
    if (store.getters.isLoggedIn) {
      next()
      return
    }    
    next('/login') 
  } else {
    next() 
  }
})

export default router

然后是 store 文件夹中 index.js 的 store

import Vue from 'vue'
import Vuex from 'vuex'
import * as patient from './modules/patient.js'
import * as appointment from './modules/appointment.js'
import * as user from './modules/user.js'
import * as notification from './modules/notification.js'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {},
    modules: {
        user,
        patient,
        appointment,
        notification
    }
})

最后是嵌套在 App.vue 中的 nabar.vue 组件。Ps 我已经取出导航抽屉和底部导航以减少代码。

<template>
    <nav>       
    <v-app-bar app dark>
        <v-btn text rounded dark v-on:click='showDrawer = !showDrawer'>
            <v-icon class='grey--text' left>menu</v-icon>
        </v-btn>      
      <v-toolbar-title d-sm-none>
        <span class='font-weight-light'>SASSA</span>      
      </v-toolbar-title>
      <v-spacer></v-spacer>   
      <!-- Log in button  -->
      <v-btn text rounded dark v-on:click='login' v-show='!isLoggedIn'>
        <span>Login</span>
        <v-icon class='grey--text' right>arrow_forward</v-icon>
      </v-btn>
      <!-- Log out button  -->
      <v-btn text rounded dark v-on:click='logout' v-show='isLoggedIn'>
        <span>Logout</span>
        <v-icon class='grey--text' right>exit_to_app</v-icon>
      </v-btn>
    </v-app-bar>
    </nav>
</template>

<script>
  import { mapState } from 'vuex'
    export default {
        data(){
            return {
              activeBtn: 1,
              showDrawer: false,
                links: [                    
                    { title: 'Appointments', icon: 'calendar_today', link: '/appointments'},
                    { title: 'New Appointment', icon: 'event', link: '/create-appointment'}
                ]          
            }
        },
    computed: {
      isLoggedIn() {
        var result = (this.$store.getters['isLoggedIn'] == "true")           
        return result
      },      
      ...mapState(['user'])
    },

    methods: {
      logout() {
        this.$store.dispatch('user/logout')
        .then(() => {
          this.$router.push('/login')
        })
      },
      login() {
        this.$router.push('/login')
      }
    }
    }
</script>

这是我尝试访问路由器中的商店的地方

    if (store.getters.isLoggedIn) {

任何帮助将不胜感激

下面是 user.js 模块

import AxiosService from '../services/AxiosService.js'

export const namespaced = true

export const state = {
    status: '',             
    token:  '',             
    user:  {}               
}

export const mutations = {
    AUTH_SUCCESS(state, payload){       
        state.status = 'logged_on'
        state.token = payload.token
        state.user = payload.user
    },
    LOGG_OFF(state){
        state.status = 'logged_off'
        state.token = ''
        state.user = {}
    }
}

export const actions = {
    login({commit, dispatch}, user){            
        return AxiosService.logon(user)
        .then(response => {
            const token = response.data.auth_token
            const user = response.data.user             
            localStorage.setItem('token',token)
            commit('AUTH_SUCCESS', {token, user})
        })
        .catch(error => {           
            const notification = {
                type: 'error',
                message: 'Invalid Credentials !!!'
            }   
            dispatch('notification/add', notification, { root: true})
            throw error
        })
    },
    logout({commit}){
        localStorage.setItem('token','')
        commit('LOGG_OFF')
    }
 }

export const getters = {
    isLoggedIn: state => !!state.token,
    authStatus: state => state.status,
    getUser: state => state.user
}

标签: vue.jsvuexvuetify.jsvue-router

解决方案


嘿,我设法解决了它。

问题是因为我的模块被命名了我必须像这样访问

store.getters['user/isLoggedIn']

而不是 store.user.isLoggedIn

再次感谢。但是我仍然有导航栏没有更新的问题


推荐阅读