后台管理配置动态路由菜单

前段时间做一个后台管理项目,因为超级管理员可以给普通管理员动态更改权限,所以vue-element-admin里的写死的权限路由菜单就不太适合我,自己研究了好半天,经历了各种死循环,终于差不多弄出了一个,可能会有点啰嗦

总结一下:

我这个后台分为三个角色:超级管理员、企业管理员和普通管理员。其中,超级管理员可以查看所有的路由菜单,企业管理员也是固定的几个菜单,所以,超级管理员和企业管理员是我在前端写好的路由菜单里直接配置的权限,而普通管理员是不固定的,需要后台给我返回数据,自己拼接。

1、首先我们需要有一个登录的页面,简单点的,用户名和密码还有一个登录按钮就可以了,我用的是vue-element-admin的模板,它已经写好了,直接拿来用就可以

2、自己在src-api文件夹中新建一个js文件来写自己的登录、获取用户信息、登出等接口(也可以换掉之前的模拟接口,在api/user.js文件)。

3、点击登录按钮,这时会在这个方法里面调用store-modules-user.js里的login方法,如下:

4、store-modules-user.js里的login方法就是调用了自己的登录接口,当然,调用之前记得先引入文件

上面是我引入的登录、获取用户信息、登出的接口

5、调用登录接口后store存储返回的token等数据(根据自己的需求来,因为我后期需要用户id,所以也把用户id存进了store里)

6、这时调用同页面的getInfo方法,当然,这个方法里也同样调用了获取用户信息的接口,这步是为了获取到登录的用户的角色,调用之后,将返回的用户角色名等存到store里(我还存了其它的数据,还是那句话,哪些数据需要就存哪些)

*** 这里当时我出了一个bug:当我登录进去之后刷新页面又跳到了登录的页面,说明有关键的数据没有存储上,上网一找,token在登录调用登录接口后已经用cookie存入了浏览器,那应该就是我只把id存进了store而没有存入浏览器,才导致一刷新就失去了id,所以我用localStorage/sessionStorage存入了id,在getInfo里才获取本地存储的id在存储到store中

 7、由于普通管理员的路由菜单是后台返给我的,所以,在getInfo这个方法中,我也直接调用了获取路由菜单的接口,将返回的数据通过拼接来生成一个完整的路由菜单,最后将这个路由菜单数组保存在store中

注:路由菜单最后一定要放404,格式 :{ path: '*', redirect: '/404', hidden: true } ,切记一定要放在最后!!!

8、接下来是去src/permission.js中调用store-modules-user.js里的getInfo方法,这块与模板的代码没有区别,所以就不多叙述。在此方法中调用了store-modules-permission.js里的generateRoutes的方法

 我们去找一下这个方法,这个方法其实是根据传过来的role来判断它能看到的路由菜单。模板里原来的方法是根据角色和写好的路由菜单一一比较,最后把对应上权限的项放进一个数组里,我这里的超级管理员和普通管理员因为权限和路由菜单固定,所以直接套用的代码。而普通管理员,则是调用保存在store里的路由菜单数组,然后赋值给定义好的变量

之后需要更改的地方就没有了,就可以测试登录了。

这里我犯了一个比较大的bug:

当以普通管理员登录的时候,我进去之后菜单显示正常,可是当我不管点击哪个菜单,都给我跳到了404 。经过一番测试与排查,我找到了解决方法,是加一个延时器,加在generateRoutes方法的这个地方

之后就运行成功了,但是具体原因我其实不太明白,因为我console.log(accessedRoutes) 出来的也是正常的路由菜单

这就是大体的配置动态路由菜单的过程,作为第一次配置成功的心得。

根据权限生成动态路由及导航菜单

最近在做一个后台管理项目,涉及到一些菜单权限控制,具体实现如下:(话不多说,直接上代码)

router/index.js

const Home = resolve => require(['@/views/common/Home.vue'], resolve);
const AAA = resolve => require(['@/views/page/AAA.vue'], resolve);
const BBB = resolve => require(['@/views/pages/BBB.vue'], resolve);
const CCC= resolve => require(['@/views/pages/CCC.vue'], resolve);
let routes = [{
    path: '/',
    component: Home,
    name: '首页',
    redirect: '/AAA',
    hidden: true,
    mate: {
      icon: 'fa fa-home',
      index: 'AAA'
    },
    children: [{
      path: '/AAA',
      component: AAA,
      name: '主页'
    }]
  }]
//从服务器获取路由,进行拼接,所有模块不再以import的形式引入,只能通过require方式加载!
export const makeRoute = function (items) {
  let routes = [];
  for (var i = 0; i < items.length; i  ) {
    // console.log(items[i]);
    items[i] = formatRoute(items[i]);
    if (items[i].children) {
      //递归处理子路由的component
      items[i].children = makeRoute(items[i].children);
    }
  }
  return items;
}
//格式化路由,使component挂载到路由上,生成addRoutes可用的格式
const formatRoute = (item) => {
  let route = item;
  route.component = eval(route.component);
  return route;
}
export default routes;

main.js(登录成功时,后台返回有权限的路由并存在状态管理器vuex中)

import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
import axios from 'axios'
import store from './store'
import routes from './router/index'
import { makeRoute } from './router'
Vue.use(VueRouter)
const router = new VueRouter({
  routes
})
router.beforeEach((to, from, next) => {
  
    //如果目标路由为登陆时,恢复用户原始状态
    if (to.path === '/login') {
      window.clearInterval(window.interval);
      store.commit('logOut');
    }
    let allRoutes = store.getters.allRoutes;
    let loginStatus = store.getters.loginStatus;
  
    //登录成功时加载路由及模块
    if (from.path === '/login' && allRoutes !== '' && loginStatus) {
      let routesObj = makeRoute(store.getters.allRoutes);
      router.addRoutes(routesObj);
    }
    //没有登录时自动跳转,开发环境免登陆时注释
    if ( to.path !== '/login' && (allRoutes === '' || !loginStatus)) {
      if(sessionStorage.getItem('userInfo') === null){  
        next({ path: '/login' })
      } else {  
        //刷新当前页面
        //重置store参数
        let userInfo = JSON.parse(sessionStorage.getItem('userInfo'));
        store.commit('setUser', userInfo);
        if(userInfo.routes){
          //重新加载路由及模块
          let routesObj = makeRoute(userInfo.routes);
          router.addRoutes(routesObj);
        }
        next({path: to.path, query: to.query});
      }
    }else{
      //路由的next必须存在,否则无法进入下一页
      next();
    }
  })

备注:此方案最大的好处是不用再使用require引入每一个组件并挂载到路由

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。

vue后台管理如何配置动态路由菜单的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. xcode – 如何在Interface Builder中为NSMenu添加其他项目?

    我第一次使用Xcode.我一直在追踪一个教程,我完全被一些毫无疑问的东西所吸引.我将“菜单”从库拖动到“MainMenu.xib”窗口中.双击此菜单可使其显示.没有麻烦到目前为止.编辑这三个项目是直观的,正如删除项目一样.但是,如何添加一个项目到这个菜单呢?解决方法您想将一个NSMenuItem从库托盘拖到菜单上:您可以添加子菜单和分隔符.

  3. Swift实现侧滑菜单SWRevealViewController

    SWRevealViewControllerGithub下载地址导入我这里直接新建一个SWRevealViewController包,然后把代码直接粘贴进入在桥接文件中导入#import“SWRevealViewController.h”使用编译一下,接着新建一个MainController父容器,继承SWRevealViewController创建左侧菜单栏RightMenuController

  4. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  5. vue使用动画实现滚动表格效果

    这篇文章主要为大家详细介绍了vue使用动画实现滚动表格效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  6. 关于Vue 监控数组的问题

    这篇文章主要介绍了Vue 监控数组的示例,主要包括Vue 是如何追踪数据发生变化,Vue 如何更新数组以及为什么有些数组的数据变更不能被 Vue 监测到,对vue监控数组知识是面试比较常见的问题,感兴趣的朋友一起看看吧

  7. Vue子组件props从父组件接收数据并存入data

    这篇文章主要介绍了Vue子组件props从父组件接收数据并存入data的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. Vue h函数的使用详解

    本文主要介绍了Vue h函数的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  10. vue+Element ui实现照片墙效果

    这篇文章主要为大家详细介绍了vue+Element ui实现照片墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部