vue-element-admin 实现动态路由(从后台查询出菜单列表绑定侧边栏)

1. 在路由实例中保留基础路由

router/index.js中只需要保留基础路由,其他的都删了

2. 获取用户菜单,并保存到Vuex中

stroe/modules/user.js中,有个getInfo方法查询用户基本信息,返回了用户的菜单列表

// get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response
        if (!data) {
          reject('Verification failed, please Login again.')
        }
        console.log(data)
        const menus =
        [{
          path: '/books',
          component: 'Layout',
          children: [{
            path: 'index',
            name: 'AddressBook',
            component: 'workbench/addressbook',
            meta: { title: '通讯录', icon: 'company' }
          }]
        },
        {
          path: '/systool',
          component: 'Layout',
          redirect: '/systool/coder',
          name: 'SysTool',
          meta: { title: '实验室', icon: 'example' },
          children: [
            {
              path: 'calendar',
              name: 'Calendar',
              component: 'workbench/calendar',
              meta: { title: '日程', icon: 'table' }
            }
          ]
        }]
        const { name, avatar, companyName, employeeid } = data
        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        commit('SET_CMPNAME', companyName)
        commit('SET_USERID', employeeid)
        commit('SET_MENUS', menus)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  }
user.js
const getters = {
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name,
  cmpname: state => state.user.cmpname,
  userid: state => state.user.userid,
  menus: state => state.user.menus
}
export default getters
getter.js

 

3.动态生成权限路由

根据环境配置导入组件,在vue中,将菜单路径作为参数,实现路由地址的注入

在 src/router 文件夹下,建立两个文件,各只需添加一行代码, 定义导入方法

src/router/_import_development.js
//开发环境导入组件
module.exports = file => require('@/views' + file + '.vue').default // vue-loader at least v13.0.0+

--------------------------------------------------------------------- src/router/_import_production.js
//生产环境导入组件 module.exports = file => () => import('@/views' + file + '.vue')

A,组件导入 —— _import

//获取组件的方法
const _import = require('./router/_import_' + process.env.NODE_ENV)

// .......

//导入路径下的组件
route.component = _import(route.path)

 

B,在路由钩子中,过滤路由,并生成路由

核心在src目录下的permission.js中,router.beforeEach路由钩子

  1 import router from './router'
  2 import store from './store'
  3 import {
  4   Message
  5 } from 'element-ui'
  6 import NProgress from 'nprogress' // progress bar
  7 import 'nprogress/nprogress.css' // progress bar style
  8 import {
  9   getToken
 10 } from '@/utils/auth' // get token from cookie
 11 import getPageTitle from '@/utils/get-page-title'
 12 import Layout from '@/layout'
 13 const _import = require('./router/_import_' + process.env.NODE_ENV) // 获取组件的方法
 14 
 15 NProgress.configure({
 16   showSpinner: false
 17 }) // NProgress Configuration
 18 
 19 const whiteList = ['/login'] // no redirect whitelist
 20 
 21 router.beforeEach(async(to, from, next) => {
 22   // start progress bar
 23   NProgress.start()
 24 
 25   // set page title
 26   document.title = getPageTitle(to.meta.title)
 27 
 28   // determine whether the user has logged in
 29   const hasToken = getToken()
 30 
 31   if (hasToken) {
 32     if (to.path === '/login') {
 33       // if is logged in, redirect to the home page
 34       next({
 35         path: '/'
 36       })
 37       NProgress.done()
 38     } else {
 39       const hasGetUserInfo = store.getters.name
 40       if (hasGetUserInfo) {
 41         next()
 42       } else {
 43         try {
 44           // get user info
 45           await store.dispatch('user/getInfo')
 46           if (store.getters.menus.length < 1) {
 47             global.antRouter = []
 48             next()
 49           }
 50           const menus = filterAsyncRouter(store.getters.menus) // 1.过滤路由
 51           router.addRoutes(menus) // 2.动态添加路由
 52           global.antRouter = menus // 3.将路由数据传递给全局变量,做侧边栏菜单渲染工作
 53           next({
 54             ...to,
 55             replace: true
 56           }) // hack方法 确保addRoutes已完成 ,set the replace
 57         } catch (error) {
 58           // remove token and go to login page to re-login
 59           await store.dispatch('user/resetToken')
 60           Message.error(error || 'Has Error')
 61           next(`/login?redirect=${to.path}`)
 62           NProgress.done()
 63         }
 64       }
 65     }
 66   } else {
 67     /* has no token*/
 68 
 69     if (whiteList.indexOf(to.path) !== -1) {
 70       // in the free login whitelist, go directly
 71       next()
 72     } else {
 73       // other pages that do not have permission to access are redirected to the login page.
 74       next(`/login?redirect=${to.path}`)
 75       NProgress.done()
 76     }
 77   }
 78 })
 79 
 80 router.afterEach(() => {
 81   // finish progress bar
 82   NProgress.done()
 83 })
 84 
 85 // 遍历后台传来的路由字符串,转换为组件对象
 86 function filterAsyncRouter(asyncRouterMap) {
 87   const accessedRouters = asyncRouterMap.filter(route => {
 88     if (route.component) {
 89       if (route.component === 'Layout') {
 90         route.component = Layout
 91       } else {
 92         route.component = _import(route.component) // 导入组件
 93       }
 94     }
 95     if (route.children && route.children.length) {
 96       route.children = filterAsyncRouter(route.children)
 97     }
 98     return true
 99   })
100 
101   return accessedRouters
102 }

 

4.最后一步,合并路由

posted @ 2019-08-13 15:32  胡椒面  阅读(38106)  评论(23编辑  收藏  举报