Accessing Vuex state when defining Vue-Router routes

删除回忆录丶 提交于 2019-11-27 05:33:04

问题


I have the following Vuex store (main.js):

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

Vue.use(Vuex)

//init store
const store = new Vuex.Store({
    state: {
        globalError: '',
        user: {
            authenticated: false
        }
     },
     mutations: {
         setGlobalError (state, error) {
             state.globalError = error
         }
     }
})

//init app
const app = new Vue({
    router: Router,
    store,
    template: '<app></app>',
    components: { App }
}).$mount('#app')

I also have the following routes defined for Vue-Router (routes.js):

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

//define routes
const routes = [
    { path: '/home', name: 'Home', component: Home },
    { path: '/login', name: 'Login', component: Login },
    { path: '/secret', name: 'Secret', component: SecretPage, meta: { requiresLogin: true }
]

I'm trying to make it so that if the Vuex store's user object has authenticated property false, have the router redirect the user to the Login page.

I have this:

Router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresLogin) && ???) {
        // set Vuex state's globalError, then redirect
        next("/Login")
    } else {
        next()
    }
})

The problem is I don't know how to access the Vuex store's user object from inside the beforeEach function.

I know that I can have the router guard logic inside components using BeforeRouteEnter, but that would clutter up each component. I want to define it centrally at the router level instead.


回答1:


As suggested here, what you can do is to export your store from the file it is in and import it in the routes.js. It will be something like following:

You have one store.js:

import Vuex from 'vuex'

//init store
const store = new Vuex.Store({
    state: {
        globalError: '',
        user: {
            authenticated: false
        }
     },
     mutations: {
         setGlobalError (state, error) {
             state.globalError = error
         }
     }
})

export default store

Now in routes.js, you can have:

import Vue from 'vue'
import VueRouter from 'vue-router'
import store from ./store.js

Vue.use(VueRouter)

//define routes
const routes = [
    { path: '/home', name: 'Home', component: Home },
    { path: '/login', name: 'Login', component: Login },
    { path: '/secret', name: 'Secret', component: SecretPage, meta: { requiresLogin: true }
]

Router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresLogin) && ???) {
        // You can use store variable here to access globalError or commit mutation 
        next("/Login")
    } else {
        next()
    }
})

In main.js also you can import store:

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

Vue.use(Vuex)

import store from './store.js'

//init app
const app = new Vue({
    router: Router,
    store,
    template: '<app></app>',
    components: { App }
}).$mount('#app')



回答2:


I ended up moving the store out of main.js and into store/index.js, and importing it into the router.js file:

import store from './store'

//routes

const routes = [
    { path: '/home', name: 'Home', component: Home },
    { path: '/login', name: 'Login', component: Login },
    { path: '/secret', name: 'Secret', component: SecretPage, meta: { requiresLogin: true }
]    

//guard clause
Router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresLogin) && store.state.user.authenticated == false) {
        store.commit("setGlobalError", "You need to log in before you can perform this action.")
        next("/Login")
    } else {
        next()
    }
})



回答3:


Managing your location state separate from the rest of your application state can make things like this harder than they maybe need to be. After dealing with similar problems in both Redux and Vuex, I started managing my location state inside my Vuex store, using a router module. You might want to think about using that approach.

In your specific case, you could watch for when the location changes within the Vuex store itself, and dispatch the appropriate "redirect" action, like this:

dispatch("router/push", {path: "/login"})

It's easier than you might think to manage the location state as a Vuex module. You can use mine as a starting point if you want to try it out:

https://github.com/geekytime/vuex-router




回答4:


This is how i would to it.

In App.vue, I will keep a watcher on cookie that stores authentication details. ( Obviously I would store a token containing authentication details as cookie after authentication )

Now whenever this cookie becomes empty, I will route the user to /login page. Logging out deletes the cookie. Now if user hit back after logging out, now since the cookie doesnot exist, ( which requires user to be logged in ), user will be routed to login page.



来源:https://stackoverflow.com/questions/42603909/accessing-vuex-state-when-defining-vue-router-routes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!