从后端获取路由表,根据路由表展示权限菜单栏

本文详细阐述了如何从前端和后端同步权限路由的过程,包括路由表的结构、后端返回的路由表转换为前端可识别格式的方法,以及如何利用Vue的动态路由实现权限菜单的动态展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文献:http://www.devopser.org/articles/2019/04/29/1556524856420.html

从后端获取路由表,根据路由表展示权限菜单栏

前端真实的路由表长这样

import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'
import {getUserRouters} from "../api/user"
Vue.use(Router)
import Layout from '@/layout'
export const constantRoutes = [
//平台管理
  {
    path: '/platformManage',
    component: Layout,
    redirect: '/platformManage',
    name: 'platformManage',
    meta: {
      title: '平台管理',
      icon: '平台管理'
    },
    children: [
      {
        path: '/objectManage',
        // name: "objectManage",
        component: () => import('@/views/platformManage/objectManage'),
        meta: { 
          title: '对象管理',
          icon: '对象管理'
        },
        redirect:'/objectManage/organManage',
        children: [
          {
            // path: '/objectManage/organManage',
            path: 'organManage',
            component: () => import('@/views/platformManage/objectManage/organManage'),
            hidden: true,
            isShow: true,
            meta: { title: '机构管理' }
          },
          {
            // path: '/objectManage/branchManage',
            path: 'branchManage',
            component: () => import('@/views/platformManage/objectManage/branchManage'),
            hidden: true,
            isShow: true,
            meta: { title: '部门管理' }
          },
          {
            // path: '/objectManage/userManage',
            path: 'userManage',
            component: () => import('@/views/platformManage/objectManage/userManage'),
            hidden: true,
            isShow: true,
            meta: { title: '用户管理' }
          },
          {
            // path: '/objectManage/userManage',
            path: 'menuManage',
            component: () => import('@/views/platformManage/objectManage/menuManage'),
            hidden: true,
            isShow: true,
            meta: { title: '菜单管理' }
          },
          {
            // path: '/objectManage/userManage',
            path: 'submitManage',
            component: () => import('@/views/platformManage/objectManage/submitManage'),
            hidden: true,
            isShow: true,
            meta: { title: '报送菜单管理' }
          }
        ]
      },
      {
        path: '/powerManage',
        component: () => import('@/views/platformManage/powerManage'),
        meta: { title: '权限管理', icon: "权限管理" },
        redirect:'/powerManage/resourceAllocation',
        children: [
          {
            path: 'resourceAllocation',
            component: () => import('@/views/platformManage/powerManage/resourceAllocation'),
            hidden: true,
            isShow: true,
            meta: { title: '资源分配' }
          },
          {
            path: 'dataAllocation',
            component: () => import('@/views/platformManage/powerManage/dataAllocation'),
            hidden: true,
            isShow: true,
            meta: { title: '数据分配' }
          }
        ]
      }
    ]
  },

]

后端的路由表长这样

export const constantRoutes = [
{
      "path": "/platformManage",
      "component": "Layout",
      "hidden": 0,
      "isShow": "0",
      "meta": {
          "title": "平台管理",
          "icon": "dashboard"
      },
      "children": [
          {
              "path": "/objectManage",
              "component": "/platformManage/objectManage",
              "hidden": 0,
              "isShow": "0",
              "meta": {
                  "title": "对象管理"
              },
              "children": [
                  {
                      "path": "organManage",
                      "component": "/platformManage/objectManage/organManage",
                      "hidden": 0,
                      "isShow": "0",
                      "meta": {
                          "title": "机构管理"
                      }
                  },
                  {
                      "path": "branchManage",
                      "component": "/platformManage/objectManage/branchManage",
                      "hidden": "1",
                      "isShow": 0,
                      "meta": {
                          "title": "部门管理"
                      }
                  },
                  {
                      "path": "userManage",
                      "component": "/platformManage/objectManage/userManage",
                      "hidden": "1",
                      "isShow": "0",
                      "meta": {
                          "title": "用户管理"
                      }
                  },
                  {
                      "path": "menuManage",
                      "component": "/platformManage/objectManage/menuManage",
                      "hidden": "1",
                      "isShow": "0",
                      "meta": {
                          "title": "菜单管理"
                      }
                  },
                  {
                      "path": "submitManage",
                      "component": "/platformManage/objectManage/submitManage",
                      "hidden": "1",
                      "isShow": "0",
                      "meta": {
                          "title": "报送菜单管理"
                      }
                  }
              ]
          },
          {
              "path": "/powerManage",
              "component": "/platformManage/powerManage",
              "hidden": "1",
              "isShow": "0",
              "meta": {
                  "title": "权限管理"
              },
              "children": [
                  {
                      "path": "resourceAllocation",
                      "component": "/platformManage/powerManage/resourceAllocation",
                      "hidden": "1",
                      "isShow": "0",
                      "meta": {
                          "title": "资源分配"
                      }
                  },
                  {
                      "path": "dataAllocation",
                      "component": "/platformManage/powerManage/dataAllocation",
                      "hidden": "1",
                      "isShow": "0",
                      "meta": {
                          "title": "数据分配"
                      }
                  }
              ]
          }
      ]
  }
]

重点来了,我们看下这个后端给的路由表,component属性返回的是字符串,需要我们把它转换成() => import(’@/views/XX/XX’)这种格式的才行。

export function rFormat(routers) {
  // 简单检查是否是可以处理的数据
  if (!(routers instanceof Array)) {
    return false
  }
  // 处理后的容器
  const fmRouters = []
  routers.forEach(router => {
    const path = router.path
    const component = router.component
    const name = router.name
    const hidden = Boolean(router.hidden) 
    let children = router.children
    const meta = router.meta
    const isShow = Boolean(router.isShow)
    const redirect = router.redirect
    console.log("component:::", component)
    // 如果有子组件,递归处理
    if (children && children instanceof Array) {
      children = rFormat(children)
    }
    const fmRouter = {
      path: path,
      component(resolve) {
        // 拼出相对路径,由于component无法识别变量
        // 利用Webpack 的 Code-Splitting 功能
        if (router.component === 'Layout') {
		// Layout作为特殊组件处理,当然后端也可以写成'/layout/Layout.vue
          require(['@/layout'], resolve)
        } else {
		// '@/views'要拼接进去,组件直接返回'@/views/xxxx/xxx.vue',然后require([compoent],resolve)会报错
          require(['@/views' + component], resolve)
        }
      },
      name: name,
      hidden: hidden,
      children: children,
      meta: meta,
      isShow: isShow,
      redirect: redirect
    }
    fmRouters.push(fmRouter)
  })
  return fmRouters
}
//保留的基础路由
export const constantRoutes = [
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    name: 'Dashboard',
    hidden: true,
    children: [{
      path: 'dashboard',
      component: () => import('@/views/dashboard/index')
    }]
  },
  { path: '*', redirect: '/dashboard', hidden: true },
    {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },
]

const createRouter = () => new Router({
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes,
  // mode: 'history',
})

const router = createRouter()

路由导航守卫

逻辑:
导航守卫中要做的事就是判断用户是否登录,没登录就去登录,登录完就去获取用户信息。获取用户信息这一步就会拿到用户的信息(姓名,角色,权限[url/element/菜单])。所以“拿到路由json数据,转换成vue可用路由,添加到当前路由”这波操作就放到登录成功后获取用户信息这里完成即可。
参考文献中是在此处判断是否登录成功的逻辑,如果你项目vuex中已经有GetInfo这个方法,在此处可以使用store.dispatch(‘GetInfo’),就是获取用户信息的动作,但在我项目中获取路由表是一个单独接口所以直接在这里调了。

let asyncRouter//用来获取后台拿到的路由
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆
router.beforeEach((to, from, next) => {
  if (to.path === '/login') {
    next();
  } else {
    //let token = store.state.user.token
    //let user=store.state.user.name
    //if (token === 'null' || token === ''||token === undefined) {
    // if (!sessionStorage.getItem('user')) {
      //next('/login');
   // } else {

      // store.dispatch("user/getInfo")
   //   next();
    //}
    let userRouter = get('USER_ROUTER')
    if (!asyncRouter) {
      if (!userRouter) {
        let params = {name: "admin"}
        getUserRouters(params).then((res) => {
          asyncRouter = res.data.data
          save('USER_ROUTER', asyncRouter)
          go(to, next)
        }).catch(err => { console.error(err) })
      } else {
        asyncRouter = userRouter
        go(to, next)
      }
    } else {
      next()
    }
  }
});

获取菜单权限路由表后,会保存在名为USER_ROUTER的localStorage里,此时即可对asyncRouter进行格式转换,并将转换后的表新增到路由的routes里就完成了。

function go (to, next) {
  asyncRouter = rFormat(asyncRouter)
  router.addRoutes(asyncRouter)
  asyncRouter.forEach((item, index) => {
    router.options.routes.push(item)
  })
  next({...to, replace: true})
  console.log("LLLL:", router)
}

function save (name, data) {
  localStorage.setItem(name, JSON.stringify(data))
}

function get (name) {
  return JSON.parse(localStorage.getItem(name))
}

export default router

本人再次发表声明:参考文献:http://www.devopser.org/articles/2019/04/29/1556524856420.html,对参考文献的作者‘罐头鱼 - devopser”表示由衷的感谢!感谢这个开源的好时代,前人栽树,后人乘凉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值