web-dev-qa-db-ja.com

Vue-Routerルートを定義するときにVuex状態にアクセスする

次のVuexストア(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')

また、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 }
]

Vuexストアのuserオブジェクトにauthenticatedプロパティがfalseの場合、ルーターがユーザーをログインページにリダイレクトするようにしようとしています。

私はこれを持っています:

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

問題は、beforeEach関数内からVuexストアのuserオブジェクトにアクセスする方法がわからないことです。

BeforeRouteEnterを使用してコンポーネント内にルーターガードロジックを持つことができることは知っていますが、それは各コンポーネントを混乱させます。代わりに、ルーターレベルで一元的に定義します。

22
Ege Ersoz

here のように、ストア内のファイルからストアをエクスポートし、routes.js。次のようなものになります。

1つ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

これで、routes.jsで次のことができます:

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()
    }
})

main.jsstoreをインポートすることもできます:

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

ロケーション状態を他のアプリケーション状態とは別に管理すると、このようなことが必要以上に難しくなる可能性があります。 ReduxとVuexの両方で同様の問題に対処した後、routerモジュールを使用して、Vuexストアの内部状態insideの管理を開始しました。あなたはそのアプローチを使うことを考えたいかもしれません。

特定のケースでは、Vuexストア内で場所がいつ変更されるかを監視し、次のような適切な「リダイレクト」アクションをディスパッチできます。

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

場所の状態をVuexモジュールとして管理するのは思っているよりも簡単です。試してみたい場合は、出発点として使用できます。

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

3
Chris Jaynes

最終的にストアをmain.jsからstore/index.jsに移動し、router.jsファイルにインポートしました。

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()
    }
})
1
Ege Ersoz

これは私がそれをする方法です。

App.vueでは、認証の詳細を保存するCookieを監視します。 (明らかに、認証後に認証の詳細を含むトークンをCookieとして保存します)

このCookieが空になるたびに、ユーザーを/ loginページにルーティングします。ログアウトすると、Cookieが削除されます。 Cookieが存在しないため(ログアウトするとユーザーがログインする必要があるため)、ユーザーがログアウト後に戻ってきた場合、ユーザーはログインページにルーティングされます。

0
chirag jain