今天记录一下Vue权限菜单(动态路由),在我们写后台的时候用的比较多,Vue的权限菜单分两种,一种是通过本地进行,根据账号的权限进行筛选出可用的权限,组合菜单并在页面上渲染显示,另一种是根据登录的账号,后端直接回可用的权限菜单,前端进行整合渲染。第二种在日常中使用比第一种的情况多些,本篇文章讲述记录的也是第二种方式。我这里使用的是 element-ui的Admin 模板。

一、新建请求的js

我这里是新建了一个请求的js,你们可以直接将这个方法写在你们现在的请求js里面。
src目录下新建一个文件夹api,新建是一个名request的js文件。

request.js代码:

//这个request 是模板自带的,封装了axios的request,在utils目录下
import request from '@/utils/request'export default {//...其他的请求// 获取权限菜单列表getRoleMenu(){return request({url: `项目请求url`,method: 'get',})},// ...其他的请求//
}

二、新建一个获取菜单的js

src目录下新建一个文件夹menu,在menu下新建一个menu.js

menu.js代码:

import Layout from '@/layout'//引入admin的layout布局
import router from '../router'//引入router
import request from '../api/request.js'//自定义封装的请求
import store from '../store'//Vuexexport default {// 获取路由菜单getMenu() {return new Promise((resolve, reject) => {return request.getRoleMenu().then(res => {/*  回来的数据格式参考// [{//   type:1,//1表示有子路由,0则没有//   path: '路径',//   component: Layout,//   children: [{//     path: '',//     name: '名称',//     component: '页面路径',//     meta: {//       title: '页面标题',//       icon: '图标'//     },//     children: []//如果有子路由则需要写//   }]// }]*///声明一个空数组,用来装处理好的菜单信息const result = []// 获取到路由菜单,进行递归数据处理this.parseRoute(res.data, result, 1)// 添加菜单this.addMenu(result)//缓存用户菜单,我这里使用的是sessionStorage,用localStorage也可以sessionStorage.setItem("route", JSON.stringify(res.data))// 输出成功resolve()}).catch(err =>{reject()})})},// 对路由菜单递归数据处理parseRoute(fullList, resultList, step) {return new Promise((resolve, reject) => {let result = []// 路由类型申明,0表示没有二级路由,1表示有一级路由const typeArray = [0, 1]// 循环进行数据处理for (let i = 0; i < fullList.length; i++) {const itemElement = fullList[i]let routerObject = nullconst childrenList = []// 路由类型过滤,如果回来的路由类型不存在,则直接结束当前循环进行下一次循环if (!typeArray.includes(itemElement.type)) {continue}//对当前执行步骤进行判断,step 等于1,则属于主路由,反之则属于子路由if (step === 1) {routerObject = {path: itemElement['routePath'],component: Layout,children: [{path: itemElement['routePath'],name: itemElement['name'],component: resolve => require([`@/views${itemElement.componentsPath}`], resolve),meta: {title: itemElement['name'],icon: itemElement['icon']},children: childrenList}]}} else {routerObject = {path: itemElement['routePath'],name: itemElement['name'],component: resolve => require([`@/views${itemElement.componentsPath}`], resolve),meta: {title: itemElement['name'],icon: itemElement['icon']},children: childrenList}}const itemResult = []//对主路由尽心判断,满足条件则进行递归if (itemElement['nextMenuList'] != null && itemElement['nextMenuList'].length) {this.parseRoute(itemElement['nextMenuList'], itemResult, step + 1)}//将组装好的子路由信息插入数组for (let j = 0; j < itemResult.length; j++) {childrenList.push(itemResult[j])}//判断子路由数组长度if (childrenList.length === 0) {//不存在子路由if (step === 1) {//如果是主路由则删除第一个子路由,如果不删除则会出现一个空的父菜单delete routerObject.children[0].children} else {//如果是子路由,则删除子路由下的子路由,删除的这个子路由是空的,必须需要删除,否则也会出现一个空的菜单delete routerObject.children}} else {//存在子路由if (step === 1) {如果是主路由,则添加meta和子路由列表routerObject.meta = routerObject.children[0].metarouterObject.children = childrenList// console.log(routerObject)}}//插入组装好的数据resultList.push(routerObject)//插入最终完整的数据列表result.push(routerObject)}//输出已经组装好并且能用的数据resolve(result)})},// 添加菜单addMenu(data) {return new Promise((resolve, reject) => {// 在处理完的菜单列表数据后面插入404页面,404必须存在菜单列表的最后一项,否则会对所有页面进行拦截,并跳转404页面data.push({path: '*',redirect: '/404',hidden: true})// 打印菜单列表// console.log(data)// 将可用的路由权限列表存入Vuexstore.dispatch('user/modifyMenu', data)// 添加菜单router.addRoutes(data)// 将路由元注入路由对象,必须添加router.options.routes.push(data)//输出成功resolve()})},//
}

三、修改Vuex

找到在store目录下的modules/user.js打开这个js文件,
引入刚刚创建的menu.js和请求的request.js

import request from "../../api/request.js"
import menu from "../../menu/menu.js"

state里添加一个menu,也就是getDefaultState()

const getDefaultState = () => {return {token: getToken(),name: '',avatar: '',menu: []//添加一个数组用来装菜单列表}
}

并在mutations里添加一个SET_MENU的方法用来修改state里的菜单列表

  SET_MENU: (state,menu) =>{state.menu = menu}

接下来就是修改actions里的login方法和添加一个方法用来修改mutations

 //1、修改login方法在login 方法的成功回调中添加一个这个方法,用来获取权限菜单menu.getMenu()//2、添加一个方法用来修改 mutations,这个方法是跟login方法同级的modifyMenu({ commit },menu){return new Promise(resolve => {commit('SET_MENU',menu)resolve()})}

修改login方法 如图:

再在logout那个方法里清除缓存,像下面这段代码这样

logout({ commit, state }) {return new Promise((resolve, reject) => {// 清除缓存的权限菜单sessionStorage.removeItem("route")//removeToken() // must remove  token  first// resetRouter()location.reload()commit('RESET_STATE')})}

现在已经能够拿到菜单信息并能够在侧边栏菜单显示了,控制台还有个报错,只是说一刷新页面就会没有,只能够通过地址栏跳转,下一步我们先来做路由/菜单的持久化。

四、修改 router,持久化处理

找到router目录,并打开index.js。引入获取权限菜单的menu.jsVuex

 import store from '../store'import menu from '../menu/menu.js'

constantRoutes 中只留下登录404首页这三个页面的router路径其他的全部不需要。类似于下面图中那样。

createRouter() 后面添加路由监听,以实现菜单的持久化。一定要放在const router = createRouter() 后面。
就像下图那样

监听路由的代码:

 //路由判断
router.beforeEach((to, from, next) => {// 判断是否有tokenif (store.state.user.token) {// 判断是否是跳转到登录页面if (to.path === '/login') next()else {//判断菜单列表if (!store.state.user.menu.length) { // 判断当前用户是否已拉取完权限菜单信息// 如果本地不存在权限菜单,则获取权限菜单,生成菜单列表if(!sessionStorage.getItem("route")){//获取路由菜单menu.getMenu().then(response =>{//保险起见,组装一次数据menu.parseRoute(JSON.parse(sessionStorage.getItem("route")), [],           1).then(res =>{//添加路由并进行跳转menu.addMenu(res).then(e =>{next({ ...to, replace: true }) // hack方法 确保addRoutes已完成})})}).catch(err =>{//失败则直接跳转登录页面next({path: 'login'})})}else{//从缓存中读取用户权限列表,并添加菜单到侧边栏和路由元menu.parseRoute(JSON.parse(sessionStorage.getItem("route")), [], 1).then(res =>{menu.addMenu(res).then(e =>{next({ ...to, replace: true }) // hack方法 确保addRoutes已完成})})}}else next({path: 'login'}) //当有权限菜单存在时,说明所有可访问路由已生成 如访问没权限的全面会自动进入登录页面}} else next({path: 'login'}); // 否则全部重定向到登录页
})

这样我们的菜单/路由持久化就

Vue 权限菜单(动态路由)详解相关推荐

  1. vue 权限管理 动态路由(6)

    1.动态生成路由 import Vue from 'vue' import Router from 'vue-router' import NProgress from 'nprogress' // ...

  2. Vue学习笔记:路由详解

    路由:Hash地址与页面的对应关系. 1.vue-router的基本使用 (1)安装vue-roouter包 npm i vue-roouter@3.5.2 -S (2)创建路由模块 在src源代码目 ...

  3. 静态路由和动态路由详解

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.静态路由 1,默认路由 2,浮动路由 二,动态路由 一.静态路由 静态路由(Static routing),一种路由的方 ...

  4. vue实现用户登录验证 + 权限验证 + 动态路由(左侧菜单栏)

    1. 技术栈说明 vue2.6 + vue-router + vuex + element-ui 2. 开始:新建项目 前提条件:在个人电脑上安装好nodejs(我的是14.15.1)之后,利用nod ...

  5. vue路由详解 --基础

    vue路由详解 --基础 1.router-link 和router-view组件 router-link相当于封装了一个a标签 router-view为组件显示的位置 <router-link ...

  6. 微信公众平台菜单编辑php,Vue.js实现微信公众号菜单编辑器步骤详解(上)

    这次给大家带来Vue.js实现微信公众号菜单编辑器步骤详解(上),Vue.js实现微信公众号菜单编辑器的注意事项有哪些,下面就是实战案例,一起来看一下. 学习一段时间Vue.js,于是想尝试着做一个像 ...

  7. Ocelot简易教程(三)之主要特性及路由详解

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9664977.html 上篇<Ocelot简易教程(二)之快速开始2>教大家如何快速跑起来一个 ...

  8. React Router路由详解

    React Router路由详解 一.基础 1.安装使用 2.React Router 中通用的组件 路由组件 BrowserRouter 和 HashRouter 路径匹配组件: Route 和 S ...

  9. vue里页面的缓存详解

    关于vue里页面的缓存详解 实用的例子ABC 往下查看 keep-alive是vue内置的一个组件,可以使被它包含的组件处于保留状态,或避免被重新渲染. 用法: 在keep-alive标签内部添加 i ...

  10. keep alive PHP,vue中keep-alive使用方法详解

    这次给大家带来vue中keep-alive使用方法详解,vue中keep-alive使用的注意事项有哪些,下面就是实战案例,一起来看一下. 1.keep-alive的作用以及好处 在做电商有关的项目中 ...

最新文章

  1. Python培训基础教程都教哪些
  2. 电脑任务管理器_电脑任务管理器没有进程怎么办
  3. 字符集详解 ------------------------ UNICODE +UTF8
  4. 【android-tips】关于string.xml的使用
  5. 拼接路径优雅方式_章泽天“学生装”穿出高级感,缎面衬衫配小香风裙,温柔又优雅...
  6. 【Hadoop】MapReduce笔记(二):MapReduce容错,任务失败处理
  7. mysql,索引命中,查询级别
  8. 详述SaltStack Salt 命令注入漏洞(CVE-2020-16846/25592)
  9. mssql 动态行转列。
  10. 使用OpenCV获取图像中某一点的像素值和修改某一点的像素值
  11. magisk卸载内置软件_手把手教你使用ADB卸载手机内置App软件
  12. Linux学习6 脚本登录主机 数组 排序 系统负载查询命令 定期备份
  13. 小卡,功能强大– M.2格式的工业通讯
  14. 解决百度推送not_same_site的问题
  15. zotero配合坚果云和papership进行文献管理
  16. WPS新建文字分享微信.docx形式_高效神器:花 5 分钟输入文字,就能自动变成 PPT...
  17. lzma java sdk,Java LZMA 磁盘与内存压缩实现
  18. Navicat premium 12 闪退问题(非有道词典问题)
  19. ​AAAI 2023 | 基于历史对比学习的时序知识图谱推理
  20. TVS/ESD国产化---雷卯电子2021上海慕尼黑展圆满收官

热门文章

  1. 车队车载调频广播电台移动发射系统的设计与应用
  2. css权重,权值与优先级解析
  3. 理解WebKit和Chromium: WebKit和Chromium组成
  4. XQuartz总是打不出“.”这个符号(MAC版)(For Mac: XQuartz cannot output this notion .)
  5. c盘那些文件可以删除
  6. iOS 多渠道打包的解决方案
  7. SSL/TLS深度解析--OpenSSL的基本使用
  8. DarkSiders
  9. Ubuntu18.04平台下C/C++编程环境搭建及OpenCV4.5.4安装
  10. 应用型本科计算机课程,应用型本科《计算机基础》课程教学改革探索