Vue路由器-如何将用户锁定在特定页面中

时间:2019-09-06 06:27:34

标签: javascript vue.js vuex vue-router

我有麻烦了...

在我的应用程序中注册后,用户需要创建一个工作区,我需要强制创建工作区,否则API将无法正常工作,但是我无法将其锁定在工作区创建页面上。

当我尝试检查用户在应用程序的第一次加载时是否已经有工作区时,由于axios请求尚未完成,vuex仍然为空...

如何确定vue路由器将等待axios接收api数据?

router.js

import Vue from 'vue'
import Router from 'vue-router'
import store from './../store'

import auth from './modules/auth'
import api from './modules/api'
import common from './modules/common'
import projects from './modules/projects'
import wabas from './modules/wabas'

Vue.use(Router)

const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [
        ...auth,
        ...api,
        ...common,
        ...projects,
        ...wabas,
    ]
})

router.beforeEach((to, from, next) => {
    store.dispatch('auth/setToken').then(() => {
        // will return an empty array
        console.log(store.getters['workspaces/workspaces'])
        if (!store.state.workspaces.workspaces.length && to.name !== 'welcome_a' && to.name !== 'welcome_b' && to.name !== 'welcome_c') {
            next({
                name: 'welcome_a'
            })
        } else {
            if (to.meta.visitor || to.name === 'welcome_a' || to.name === 'welcome_b' || to.name === 'welcome_c') {
                next({
                    name: 'home'
                })
                return
            }

            next()
        }
    }).catch(() => {
        if (to.meta.auth) {
            next({
                name: 'login'
            })
            return
        }
        next()
    })
})

export default router

router / modules / common.js

const routes = [
    {
        path: '/',
        name: 'home',
        component: () => import('../../pages/Home'),
        meta: {
            auth: true
        }
    },
    {
        path: '/bem-vindo',
        name: 'welcome_a',
        component: () => import('../../pages/WelcomeA'),
        meta: {
            auth: true
        }
    },
    {
        path: '/finalizar-cadastro',
        name: 'welcome_b',
        component: () => import('../../pages/WelcomeB'),
        meta: {
            auth: true
        }
    },
    {
        path: '/area-de-trabalho',
        name: 'welcome_c',
        component: () => import('../../pages/WelcomeC'),
        meta: {
            auth: true
        }
    }
]

export default routes

main.js

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

import localforage from "localforage";

localforage.config({
    driver: localforage.LOCALSTORAGE,
    storeName: 'positus'
})

Vue.config.productionTip = false

window._ = require('lodash')

import components from './components'

components.forEach(component => {
    Vue.component(component.name, component);
});

import helpersMixin from './support/mixins/helpers'

Vue.mixin(helpersMixin)

import notifications from './support/notifications'

Vue.use(notifications)

import bus from './support/bus'

Vue.use(bus)

import VueClipboard from 'vue-clipboard2'

Vue.use(VueClipboard)

import http from './support/http'

Vue.use(http)

store.dispatch('auth/setToken').then(() => {
    store.dispatch('auth/fetchSystemData').catch(() => {
        store.dispatch('auth/clearAuth')
    })
}).catch(() => {
    store.dispatch('auth/clearAuth')
})

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

store / modules / auth.js

import Vue from 'vue'
import authApi from '../../api/auth'
import {setHttpToken} from '../../support/http'
import axios from 'axios'
import localforage from 'localforage'
import router from '../../router'

const state = {
    user: {}
}

const getters = {
    user(state) {
        return state.user
    }
}

const actions = {
    fetchData({commit}) {
        return axios.all([
            authApi().user.get()
        ]).then(axios.spread((user) => {
            commit('SET_USER_DATA', user.data.data)
        })).catch(error => console.error(error))
    },
    fetchSystemData({dispatch}) {
        return Promise.all([
            dispatch('fetchData'),
            dispatch('workspaces/fetchData', null, {root: true})
        ]).finally(() => {
            dispatch('app/setProcessing', false, {root: true})
        })
    },
    authenticateUser({commit, dispatch}, data) {
        dispatch('app/setProcessing', true, {root: true})

        return authApi().login(data)
            .then(({data}) => {
                dispatch('setToken', data).then(() => {
                    dispatch('fetchSystemData').then(() => {
                        router.push({
                            name: 'home'
                        })
                    }).catch(() => {
                        Vue.$n('Ocorreu um erro ao receber os dados da sua conta, tente novamente mais tarde.', 'error')
                    })
                })
            }).catch(() => {
                dispatch('app/setProcessing', false, {root: true})

                Vue.$n('Algum erro ocorreu na tentativa de acessar sua conta.', 'error')
            })
    },
    setToken({dispatch}, token) {
        if (_.isEmpty(token)) {
            return dispatch('checkTokenExists').then((token) => {
                setHttpToken(token)
            })
        }

        dispatch('setTokenLocalStorage', token)
        setHttpToken(token)
        return token
    },
    setTokenLocalStorage({commit}, token) {
        if (_.isEmpty(token)) {
            localforage.removeItem('token', token)
            return
        }

        localforage.setItem('token', token)
    },
    checkTokenExists() {
        return localforage.getItem('token').then((token) => {
            if (_.isEmpty(token)) {
                return Promise.reject('NO_STORAGE_TOKEN')
            }

            return Promise.resolve(token)
        })
    },
    clearAuth({dispatch}) {
        Promise.all([
            dispatch('setTokenLocalStorage', null)
        ]).finally(() => {
            setHttpToken(null)
            router.push({
                name: 'login'
            })
        })
    },
    updateActiveWorkspace({commit}, data) {
        commit('UPDATE_ACTIVE_WORKSPACE', data)
    }
}

const mutations = {
    SET_USER_DATA(state, user) {
        state.user = user
    },
    UPDATE_ACTIVE_WORKSPACE(state, data) {
        state.user.active_workspace = data
    }
}

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

store / modules / workspaces.js

import workspacesApi from "../../api/workspaces"
import axios from "axios"

const state = {
    workspaces: []
}

const getters = {
    workspace(state) {
        return (id) => {
            return _.find(state.workspaces, (workspace) => {
                return workspace.id === id
            })
        }
    },
    workspaces(state) {
        return state.workspaces
    }
}

const actions = {
    fetchData({commit}) {
        return axios.all([
            workspacesApi().get()
        ]).then(axios.spread((workspaces) => {
            commit('SET_WORKSPACES', workspaces.data.data)
        })).catch(error => console.error(error))
    },
    setWorkspaces({commit}, data) {
        commit('SET_WORKSPACES', data)
    },
    setWorkspace({commit, state}, data) {
        let index = _.findIndex(state.workspaces, (space) => {
            return space.id === data.id
        })

        if (index >= 0) {
            commit('UPDATE_WORKSPACE', {
                index: index,
                data: data
            })
        } else {
            commit('SET_WORKSPACE', data)
        }
    }
}

const mutations = {
    SET_WORKSPACES(state, bool) {
        state.workspaces = bool
    },
    SET_WORKSPACE(state, data) {
        state.workspaces.push(data)
    },
    UPDATE_WORKSPACE(state, data) {
        state.workspaces.splice(data.index, 1, data.data);
    }
}

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

2 个答案:

答案 0 :(得分:0)

从该问题的标题开始,您可以在vue组件中添加一个钩子,该钩子将在更改路线之前运行

beforeRouteLeave (to, from, next) {
    // called when the route that renders this component is about to
    // be navigated away from.
    // has access to `this` component instance.
  }

如果您希望用户移动到他单击的下一条路线,则将在此挂接内调用next(),并将其导航到下一页。

如果您想锁定他而不导航,请使用next()之类的next(false)方法传递false

答案 1 :(得分:0)

为什么不创建一个中间件服务器端,如果用户还没有的话,它将用户重定向到工作区创建页面? laravel之类的东西

class RedirectIfWorkspaceNotCreated
{

    public function handle($request, Closure $next, $guard = null)
    {
        $user = Auth::guard($guard)->user();

        if ($user && !checkForUserWorkspace) {
            return redirect('/your/workspace/creation/page');
        }

        return $next($request);
    }
}