Vue权限路由[菜单权限/按钮权限控制]

前言

   年前完工了做了半年的铁路后台管理系统,系统整体业务比较复杂,这也是我到公司从 0 到 1 的 一个完整系统实践,做这个系统过程中踩了不少坑,也学到了很多。</br>

  做完这个系统没多久,紧接着又一个系统来了,没及时总结,惭愧哈!其实我们在做的后台管理系统大多数基础框架都一样,后台管理系统 主要的 是 角色权限管理 , 按钮权限管理 和 菜单管理 , 其它的业务主要围绕在这个基础之上进行扩展,最终 构成了 符合业务的后台管理系统.

 由于我司的项目都是采用 Vue 技术栈,那么该文章也是讲解 Vue 如何进行权限管理 进行讲解。

结尾有彩蛋哦!

权限授权登录

任何一个后台管理系统都是 首先从登录开始,登录后返回用户基本信息,以及token。

  • token :存入 sessionStronge / localStronge中,然后加入到 封装好的 Axios 的 请求头中,每次请求携带token.
  • 用户基本信息

登录成功后同时要做很多事情,具体业务具体对待。后台管理系统 登录成功后会请求当前用户的菜单权限接口,来获取用户的可访问的路由(动态路由),获取成功后, Vue Router 是不能直接使用的,必须得解析成符合 Vue Router 可识别的格式 .

登录

1 handleLogin() { 2 this.$refs.loginForm.validate(valid => { 3 if (valid) { 4 this.loading = true; 5 login(this.loginForm) 6 .then(res => { 7 if (res.code === 200) { 8 // 存放token 9 sessionStorage.setItem("tokens", res.data.token); 10 // 触发Vuex 来 加载 获取当前用户的菜单,并解析路由 11 store.dispatch("setMenuList"); 12 this.$message({ 13 message: "登录成功", 14 type: "success", 15 duration: 1000 16 }); 17 this.$router.replace({ path: "/dashboard" }); 18 } 19 }) 20 .catch(() => { 21 this.loading = false; 22 }); 23 } else { 24 console.log("error submit!!"); 25 return false; 26 } 27 }); 28 }

获取当前用户菜单,解析路由

登录成功后,本文通过 Vuex 来获取当前用户菜单和解析路由的。

store.dispatch("setMenuList");

1/* 2 * @Description: 3 * @Author: ZhangXin 4 * @Date: 2021-02-02 16:10:59 5 * @LastEditTime: 2021-02-23 23:03:30 6 * @LastEditors: ZhangXin 7 */ 8// getMenu 解析后台路由 9import { getMenu } from '../../utils/getMenu' 10// 引入路由 和 静态路由 11import router, { constantRoutes } from '../../router/index' 12const state = { 13 routerType: '', 14 // 菜单路由 15 meunList: [] 16} 17 18const mutations = { 19 SET_ROUTER_TYPE(state, type) { 20 state.routerType = type 21 }, 22 SET_ROUTER_MENULIST(state, list) { 23 // 静态路由 + 动态路由 合并 完整路由 24 const array = constantRoutes.concat(list) 25 state.meunList = array 26 router.options.routes = array 27 router.addRoutes([...array]) 28 } 29} 30 31const actions = { 32 setMenuList({ commit, state }) { 33 // 接收返回来的 路由数组 34 return new Promise((resolve, reject) => { 35 getMenu().then(res => { 36 commit('SET_ROUTER_TYPE', '') 37 commit('SET_ROUTER_MENULIST', res) 38 resolve(res) 39 }) 40 }) 41 } 42} 43export default { 44 state, 45 mutations, 46 actions 47}

解析后端返回来路由(重点)

封装好的解析后端返回来的路由,这块主要是为了在 Vuex 中使用。

1/* 2 * @Description: 3 * @Author: ZhangXin 4 * @Date: 2021-02-02 16:03:48 5 * @LastEditTime: 2021-02-23 23:09:02 6 * @LastEditors: ZhangXin 7 */ 8import Layout from '@/layout' 9import {getUserAuthMenu} from '@/api/user' 10 11 12 13/** 14 * @description: 解析后端返回来的菜单树 15 * @param {*} data 后端返回来的路由树 16 * @param {*} arr 菜单 17 * @return {*} 18 */ 19function tree(data, arr) { 20 data.forEach((datas, index) => { 21 arr.push({ 22 path: datas.path, 23 name: datas.name, 24 types: datas.types, 25 hidden: datas.hidden == 'true' ? true : false, 26 // 当时这块踩坑了 27 component: datas.component === 'Layout' ? Layout : resolve => require([`@/views/${datas.component}.vue`], resolve), 28 meta: { 29 title: datas.meta.title, 30 icon: datas.meta.icon, 31 // 用来存放按钮权限 32 button: datas.meta.button 33 }, 34 // redirect: datas.redirect, 35 id: datas.id, 36 // 子路由 37 children: [] 38 }) 39 40 if (datas.children) { 41 const childArr = tree(datas.children, []) 42 arr[index].children = childArr 43 } 44 }) 45 return arr 46} 47 48 49/** 50 * @description: 获取当前登录用户的菜单 51 * @param {*} 52 * @return {*} 53 */ 54export function getMenu() { 55 return new Promise(function (resolve, reject) { 56 getUserAuthMenu().then(res => { 57 if(res.code === 200){ 58 const datas = res.data 59 // 调用 tree 来解析后端返回来的树 60 resolve(tree(datas, [])) 61 } 62 63 }) 64 }) 65} 66

后端接收路由格式

<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b363801ea8c948258fc3229d0bb3c464~tplv-k3u1fbpfcp-zoom-1.image"/>

前端接收到的真实菜单树

<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5fd97a6a539d4f09baaf1d9cd5b256c6~tplv-k3u1fbpfcp-zoom-1.image" />

页面刷新,路由丢失

到此为止,已经实现了 Vue 动态权限控制 ,别高兴的太早,哈哈,一刷新页面,页面就进入了 404 页面 。

这是为什么呢 ?

因为存入 Vuex 中的数据,一刷新页面,就会清空,那么当然找不到当前路由,就进入 404 页面了 .

如何处理呢?

**一、 可以 将 静态和 动态 构成的完整路由 存放在 sessionStronge / localStronge 中,然后页面刷新时,通过在 全局入口文件 App.vue 的 生命周期 created 中 ,将 router = sessionStronge / localStronge 存入的完整的路由,页面在刷新时,它会重新加载完整的路由。 **

二、如果是使用Vuex来获取和解析用户菜单的话, 那么你可以在全局入口文件 App.vue 的 生命周期 created 中 ,再次执行 Vuex Action 来重新加载用户菜单

我这块直接在 App.vue 的 生命周期 created 中 , 再次执行了 Vuex 来进行加载和解析,没有做其它操作。 当然了,具体业务具体对待。

1<template> 2 <div id="app"> 3 <router-view v-if="isRouterAlive" /> 4 </div> 5</template> 6 7<script> 8import store from "@/store"; 9export default { 10 name: "App", 11 provide() { 12 return { 13 reload: this.reload 14 }; 15 }, 16 data() { 17 return { 18 isRouterAlive: true 19 }; 20 }, 21 methods: { 22 reload() { 23 this.isRouterAlive = false; 24 this.$nextTick(() => (this.isRouterAlive = true)); 25 } 26 }, 27 created() { 28 //只要刷新页面,就会重新加载路由树,保证了路由不会丢失数据 29 store.dispatch("setMenuList"); 30 } 31}; 32</script> 33

总结

核心思想

  • 1.定义符合 当前项目业务路由格式,前后端按这个接收传递
  • 2.前端解析后端返回的动态路由,生成Vue Router 可识别格式,最后拼接完整路由
  • 3.刷新路由丢失处理
<br/>

按钮权限控制

  • 1.当前组件 路由 携带可使用的 按钮权限,存入数组中,通过v-if 来判断是否显示
  • 2.登录时,单独获取整个系统的按钮权限,将获取到的所有按钮 存入一个数组中,放入全局中,然后,通过 v-if 来判断是否显示
  • **3. ............ **

公众号

::: warning 关注微信公众号: 获取更多前端资讯 :::

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )