序言

因为打算做前后端分离的权限控制,并且生成动态的权限菜单,但是发现vue-admin-template是前端根据角色控制页面,并且代码写死在前端,我觉得这样不好,后面用户管理的时候添加了个角色前端就得改代码,就查阅了下资料,根据后台来传入路由表,然后再通过router.addRouters();方法将路由表添加进去;

具体

1.后台传入路由表数据数据格式
{
	"message": "success",
	"success": true,
	"code": 20000,
	"data": {
		"name": "Uncle",
		"avatar": "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
		"roles": ["admin"],
		"routers": [{
			"name": "Test_It",
			"path": "/test",
			"component": "Layout",
			"children": [{
				"name": "Test_It_c",
				"path": "index",
				"component": "Test",
				"meta": {
					"icon": "example",
					"title": "后台"
				},
			}]
		}]
	}
}
2.前端页面将json格式化成js对象,重点是将compoent转化真实的组件对象

2.1 格式化工具

import Test from '@/views/form/index'
import Layout from '@/layout'
export default function (routers) {
  return filterAsyncRouter(routers)
}
//将后台返回的json权限数据格式化(递归遍历子节点)
export const  filterAsyncRouter=(asyncRouterMap) =>{ //遍历后台传来的路由字符串,转换为组件对象
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) {
        if (route.component === 'Layout') { //Layout组件特殊处理
          route.component = Layout
        } else {
          route.component = Test
        }
    }
    if (route.children && route.children.length) {

      route.children = filterAsyncRouter(route.children)
    }
    return true
  })
  return accessedRouters
}

2.2 获取路由表并且格式化

import {constantRouterMap} from '@/router';
const user = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers; //路由访问
      state.routers = constantRouterMap.concat(routers); //菜单显示
    }
  },

  actions: {
    // 获取用户信息
    GetInfo({commit,state }) {
      return new Promise((resolve, reject) => {
        getInfo(state.token).then(response => {
          const data = response.data
          commit('SET_NAME', data.name)
          commit('SET_ROLES', data.roles)
          commit('SET_AVATAR', data.avatar)
          commit('SET_ROUTERS', routerFormat(data.routers))
          resolve(response)
        }).catch(error => {
          reject(error)
        })
      })
    },
    }
3.添加路由表

全局路由拦截器

import router from './router'
import store from './store'
import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css'// Progress 进度条样式
import { Message } from 'element-ui'
import { getToken } from '@/utils/auth' // 验权

const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
  NProgress.start()
  if (getToken()) {
    if (to.path === '/login') {
      next({ path: '/' })
    } else {
      if (store.getters.name.length === 0) {
        store.dispatch('GetInfo').then(res => { // 拉取用户信息
          router.addRoutes(store.getters.routers)//添加后台路由表
          next({ ...to, replace: true })
        }).catch(e => {
          store.dispatch('FedLogOut').then(() => {
            Message.error('验证失败,请重新登录'+e.message)
            next({ path: '/login' })
          })
        })
      } else {
        next()
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next('/login')
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done() // 结束Progress
})

4.绑定路由表

路径 @/layout/componets/SideBar/index.vue
刚开始发现addRouters()之后能访问但是并没有在菜单中显示,打印出来看了下router.option.router没有添加的路由,但是自己在store里面的却有,所以这里路由绑定我就换成了store里的routers,成功显示。

    routes() {
      return this.$store.getters.routers//大坑。。
    },

源码地址

GitHub源码地址

Logo

前往低代码交流专区

更多推荐