>[success] # 动态路由加载 ~~~ 1.上个章节的实现思路,在用户第一次登陆的时候保存了用户权限,之后每次当用户进行路由跳转的时候, 都会进行一次权限匹配来匹配当前用户是否可以登陆我们要跳转的页面,这种思路需要每次都要判断 当前用户是否可以跳转对应页面 2.动态路由的思路,我们通过后台获取用户可以访问页面的数据,然后我们在第一次登陆的时候将符合该 用户的路由加入到 'vueRouter' 中 ~~~ >[danger] ##### 后台的数据格式 ~~~ 1.这次的数据格式和上个章节不同,上个章节是用权限分组为后台的返回,这个章节我们用路由的列表为 返回的权限为主 ~~~ * 格式 ~~~ { code: 200, mes: 'success', data: { token: jwt.sign({ name: userName }, 'abcd', { expiresIn: '1d' }), rules: { page: { home: true, home_index: true, about: true, argu: true, count_to: true, menu_page: true, upload: true, form: true, folder_tree: true, table_page: true, render_page: true, split_pane: true, parent: true, child: true, named_view: true, store: true, main: true }, component: { edit_button: true, publish_button: false } } } } ~~~ >[info] ## 前端实现思路 ~~~ 1.在router 我们需要将router 拆分成两个部分,一部分是不可变的'登录页','404'页面,或者死所有权限都可见 页面,另一个部分就是权限部分,这个部分会根据后台接口返回我们进行重新整合 ~~~ >[danger] ##### 路由部分 ~~~ 1.routerMap 就是权限可变部分 ~~~ ~~~ import Home from '@/views/Home.vue' import Layout from '@/views/layout.vue' export const routerMap = [ { path: '/', name: 'home', component: Layout, children: [ { path: 'home', name: 'home_index', component: Home } ] }, ] export const routes = [ { path: '/login', name: 'login', component: () => import('@/views/login.vue') }, { path: '*', component: () => import('@/views/error_404.vue') } ] ~~~ >[danger] ##### 路由守卫要做的 ~~~ 1.路由守卫这里,简单粗暴我们获取用可以访问的页面规则后,调用vuex 中的'concatRoutes' 获取可以访问的路由 然后将可访问的路由通过'addRoutes' 和每个人都可以使用的路由进行拼接 ~~~ ~~~ import Vue from 'vue' import Router from 'vue-router' import { routes } from './router' import store from '@/store' import { setTitle, setToken, getToken } from '@/lib/util' Vue.use(Router) const router = new Router({ routes }) const HAS_LOGINED = false router.beforeEach((to, from, next) => { to.meta && setTitle(to.meta.title) const token = getToken() if (token) { // 判断当前用户是否是第一次规则匹配 if (!store.state.router.hasGetRules) { store.dispatch('authorization').then(rules => { store.dispatch('concatRoutes', rules).then(routers => { // 将符合规则的路由进行拼接 router.addRoutes(routers) next({ ...to, replace: true }) }).catch(() => { next({ name: 'login' }) }) }).catch(() => { setToken('') next({ name: 'login' }) }) } else { next() } } else { if (to.name === 'login') next() else next({ name: 'login' }) } }) // router.beforeResolve router.afterEach((to, from) => { // logining = false }) export default router ~~~ >[danger] ##### 在vuex 做的 ~~~ 1.为了更好区分在vuex 的创建'src\store\module\router.js',这里做的就是讲路由进行重新整理生成一个符合使用 的路由列表 ~~~ ~~~ import { routes, routerMap } from '@/router/router' const state = { routers: routes, hasGetRules: false } const mutations = { CONCAT_ROUTES (state, routerList) { state.routers = routerList.concat(routes) state.hasGetRules = true } } const getAccesRouterList = (routes, rules) => { return routes.filter(item => { if (rules[item.name]) { if (item.children) item.children = getAccesRouterList(item.children, rules) return true } else return false }) } const actions = { concatRoutes ({ commit }, rules) { return new Promise((resolve, reject) => { try { let routerList = [] // 如果每个都符合直接 使用全部,不符合在使用递归 if (Object.entries(rules).every(item => item[1])) { routerList = routerMap } else { routerList = getAccesRouterList(routerMap, rules) } commit('CONCAT_ROUTES', routerList) resolve(state.routers) } catch (err) { reject(err) } }) } } export default { state, mutations, actions } ~~~