一个后台重要的就是权限管理了,而要实现权限,无非是要达到这几点
根据不同的权限,分配不同的后台菜单
无权限的页面不能访问
无权限的接口不能访问
1和3可以由后台轻松管理,而2则要麻烦一些,假如我们给所有页面都设置了路由,由于是单页面应用,用户访问某个页面,并不经过后台,所以用户可能会访问不属于自己权限的页面,因此我们想实现的功能是,根据用户的权限,加载相应的路由,即实现动态路由,这需要用到router.addRouters接口。
router.addRoutes
文档地址:https://router.vuejs.org/zh/api/#router-addroutes
router.addRoutes(routes: Array<RouteConfig>)
动态添加更多的路由规则。参数必须是一个符合 routes
选项要求的数组。
动态路由实现
路由设置
router文件夹下,我们设置两个文件,index.js和dynamic-router.js
index文件主要设置没有权限的路由,比如登录页面、404和403页面
import Vue from 'vue' import Router from 'vue-router' import Login from '@/pages/site/Login' import NoFind from '@/pages/site/404' import Forbidden from '@/pages/site/403' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/site/login', name: 'login', component: Login, meta:{requiresAuth:false}, }, { path: '/404', name: '404', component:NoFind, meta:{requiresAuth:false}, }, { path: '/403', name: '403', component:Forbidden, meta:{requiresAuth:false}, }, ] })
dynamic-router.js则设置我们需要动态分配的路由信息
/* * 动态路由的配置表 * 用于获取权限后,生成对应的路由,然后动态添加 * 添加新页面后,到此处进行配置 */ const routes=[ { path: '/', name: 'dashboard', component: (resolve) => require(['@/pages/layout/Layout'], resolve), meta:{requiresAuth:true,noPermission:true}, }, { path: '/index', name: 'dashboard', component: (resolve) => require(['@/pages/layout/Layout'], resolve), meta:{requiresAuth:true,noPermission:true}, children:[ { path: '/site/update-pwd', name: 'site-update-pwd', component: (resolve) => require(['@/pages/site/UpdatePwd'], resolve), meta:{requiresAuth:false,noPermission:true}, }, { path: '/administrators/index', name: 'administrators-index', component: (resolve) => require(['@/pages/permission/AdministratorsIndex'], resolve), meta:{requiresAuth:true}, }, { path: '/administrators/edit', name: 'administrators-edit', component: (resolve) => require(['@/pages/permission/AdministratorsEdit'], resolve), meta:{requiresAuth:true}, }, { path: '/administrators/pwd', name: 'administrators-pwd', component: (resolve) => require(['@/pages/permission/AdministratorsPwd'], resolve), meta:{requiresAuth:true}, }, { path: '/roles/index', name: 'roles-index', component: (resolve) => require(['@/pages/permission/RolesIndex'], resolve), meta:{requiresAuth:true}, }, { path: '/roles/edit', name: 'roles-edit', component: (resolve) => require(['@/pages/permission/RolesEdit'], resolve), meta:{requiresAuth:true}, }, ....... ] }, //其他页面则都进入404 { path: '*', redirect: '/404', meta:{requiresAuth:false,noPermission:true} } ] //根据权限获取动态路由,如果子路由用户有权限,则肯定要给父路由的权限,通过递归的方式获取有权限的路由数组 function generateRouteByPermision(routes,permission) { let filter_result=[]; for(let i=0;i<routes.length;i++){ if(routes[i].children&&routes[i].children.length>0){ let children_result=generateRouteByPermision(routes[i].children,permission) if(children_result.length>0){ routes[i].children = children_result filter_result.push(routes[i]) }else { routes[i].children = [] if(routes[i].meta.noPermission||permission.indexOf(routes[i].path)>-1){ filter_result.push(routes[i]) } } }else{ if(routes[i].meta.noPermission||permission.indexOf(routes[i].path)>-1){ filter_result.push(routes[i]) } } } return filter_result } export default { routes: routes, generateRouteByPermision:generateRouteByPermision }
在main.js中,通过路由前置守卫,获取权限并动态添加路由
main.js
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router/index' import dynamicRouter from './router/dynamic-router' import store from './store/index' import authorize from './utils/base/authorize' import netwrok from './utils/base/network' import config from './utils/config/config' import api from './utils/config/api' import toastRegistry from './components/plugins/toast/index' import confirmRegistry from './components/plugins/confirm/index' // 这里也可以直接执行 toastRegistry() Vue.use(toastRegistry) Vue.use(confirmRegistry) router.beforeEach(async (to,from,next)=>{ if(to.meta.requiresAuth===false){ //不需要登录的直接放行 next() }else if(!authorize.checkLogin()){ //如果页面需要登录,且登录失效,进入登录页面 next({ path:config.login_path, query: { redirect: to.fullPath } }) }else { //已经登录 //是否已经拉取menu,权限等信息 if(!store.state.menu_loaded){ //如果页面还没有拉取menu await netwrok.post(api.get_user_info,'',true).then((res)=>{ store.commit('SET_USER_INFO',res) //获取动态路由 let dy_routers=dynamicRouter.generateRouteByPermision(dynamicRouter.routes,res.permission); //动态添加路由 router.addRoutes(dy_routers) }) next({ ...to, replace: true }) }else{ next() } } }) /* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })