【Vue】 vue-element-admin 路由菜单配置
路由说明见官方文档:
https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/essentials/router-and-nav.html
组件渲染的数据来源
这里先说明侧边栏组件获取的路由:
src\layout\components\Sidebar\index.vue
路由是通过这个permission_routers获取的
<template>
<div :class="{'has-logo':showLogo}">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
>
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
</el-menu>
</el-scrollbar>
</div>
</template> <script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss' export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
'permission_routes',
'sidebar'
]),
activeMenu() {
const route = this.$route
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
},
showLogo() {
return this.$store.state.settings.sidebarLogo
},
variables() {
return variables
},
isCollapse() {
return !this.sidebar.opened
}
}
}
</script>
访问到Gettter.js可以看到Vuex是区分了命名空间的,对应的空间是permission
const getters = {
sidebar: state => state.app.sidebar,
size: state => state.app.size,
device: state => state.app.device,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
introduction: state => state.user.introduction,
roles: state => state.user.roles,
// permission_routes: state => state.permission.routes,
permission_routes: state => state.menu.routes,
errorLogs: state => state.errorLog.logs
}
export default getters
所以说,默认是从permission模块里的routes获取的
如果我们新开的Vuex写路由获取逻辑,这里不改的话就拿不到我们自己获取的路由了
路由权限控制
在main.js下面的permission里面:
每次跳转路由,都要从VueX拿令牌,判断用户是否有效
自己定义校验规则 和 路由获取规则即可,
这段参考Open-his来做的,路由还是前端配置,控制只展示哪些,交给后端来完成
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title' NProgress.configure({ showSpinner: false }) // NProgress Configuration /**
* no redirect whitelist
* 白名单,没有权限控制的路由地址
* @type {string[]}
*/
const whiteList = ['/login', '/auth-redirect'] /**
* 在路由跳转之前,勾子函数的控制
*/
router.beforeEach(async(to, from, next) => {
/* 启动进度条 start progress bar */
NProgress.start() /* 设置系统标签文本信息 set page title */
document.title = getPageTitle(to.meta.title) /* 从Cookie里面提取令牌 determine whether the user has logged in */
const hasToken = getToken() /* 令牌存在 */
if (hasToken) {
/* 访问登录页时直接放行 */
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
} else {
/**
* 判断当前用户的角色集合是否存在
* determine whether the user has obtained his permission roles through getInfo
* @type {any}
*/
// const hasRoles = store.getters.roles && store.getters.roles.length > 0
/* 存在则放行路由 */ // 确定用户是否已通过getInfo获得其用户
const hasName = !!store.getters.name if (hasName) {
next()
} else {
/* 没有则重新获取用户信息 */
try {
/**
* // get user info
* // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
* 根据令牌重新获取用户信息,只要角色集合
*/
const { menus } = await store.dispatch('user/getInfo') /**
* generate accessible routes map based on roles
* 创建可访问的路由表
* @type {any}
*/
// const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
const accessRoutes = await store.dispatch('menu/getAccessMenus', menus) /**
* dynamically add accessible routes
* 动态添加路由
*/
router.addRoutes(accessRoutes) /**
* 如果用户状态持续,保持路由不会丢掉历史记录
* // hack method to ensure that addRoutes is complete
* // set the replace: true, so the navigation will not leave a history record
*/
next({ ...to, replace: true })
} catch (error) {
/**
* 如果用户信息无法获取,重定向,要求用户重新登录
* remove token and go to login page to re-login
*/
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
/* 如果没有令牌,检查是否是白名单的路由 has no token*/ if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
/* 没有权限,也不是白名单,重定向到登录页面 */
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}) /* 每次跳转之后的回调勾子 */
router.afterEach(() => {
/* finish progress bar 进度条加载完成 */
NProgress.done()
})
路由获取规则Menu.js
import { asyncRoutes, constantRoutes, lastRoute } from '@/router/index' const state = {
routes: []
} const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = routes
}
} /**
* 递归路由集合,和用户的菜单进行比较,符合则打开,反之关闭
* @param routes
* @param srvMenus
*/
function generateMenus(routes, srvMenus) {
for (let i = 0; i < routes.length; i++) {
const routeItem = routes[i]
let showItem = false
for (let j = 0; j < srvMenus.length; j++) {
const srvItem = srvMenus[j] // 前后端数据通过 serPath 属性来匹配
if (routeItem.name !== undefined && routeItem.name === srvItem['menuRoute'] && srvItem['isShow'] === true) {
showItem = true
routes[i]['hidden'] = false
break
}
}
if (showItem === false) {
routes[i]['hidden'] = true
} if (routeItem['children'] !== undefined && routeItem['children'].length > 0) {
generateMenus(routes[i]['children'], srvMenus)
}
}
} const actions = {
getAccessMenus({ commit }, menus) {
return new Promise(resolve => {
const pushRouter = asyncRoutes
generateMenus(pushRouter, menus)
const routeArr = []
console.log(constantRoutes)
routeArr.push(...constantRoutes)
routeArr.push(...pushRouter)
routeArr.push(...lastRoute)
commit('SET_ROUTES', routeArr)
console.log(routeArr) /* 返回全部匹配的路由 */
resolve(routeArr)
})
}
} export default {
namespaced: true,
state,
mutations,
actions
}
前端路由表配置:
我想弄三层菜单,需要第二层再单开组件放路由才可以,这个可以查看文档说明
https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/router-and-nav.html#侧边栏
这里我就只放异步路由的配置,常量路由是所有人都能看的,没啥可表达的
/**
* 异步路由,根据用户的角色集合动态加载
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
{
path: '/system',
component: Layout,
redirect: 'noRedirect',
name: '/system',
alwaysShow: true,
meta: { title: '系统管理', icon: 'lock' },
children: [
{
path: 'rbac',
component: () => import('@/views/tt-server/system/rbac/index'),
name: '/system/rbac',
meta: { title: '权限维护', icon: 'lock' },
children: [
{
path: 'user-info',
component: () => import('@/views/tt-server/system/rbac/user-info/index'),
name: '/system/rbac/user-info',
meta: { title: '用户管理', icon: 'edit' }
},
{
path: 'role-info',
component: () => import('@/views/tt-server/system/rbac/role-info/index'),
name: '/system/rbac/role-info',
meta: { title: '角色管理', icon: 'edit' }
},
{
path: 'menu-info',
component: () => import('@/views/tt-server/system/rbac/menu-info/index'),
name: '/system/rbac/menu-info',
meta: { title: '菜单管理', icon: 'edit' }
},
{
path: 'privilege-info',
component: () => import('@/views/tt-server/system/rbac/privilege-info/index'),
name: '/system/rbac/privilege-info',
meta: { title: '权限管理', icon: 'edit' }
}
]
},
{
path: 'common',
component: () => import('@/views/tt-server/system/common/index'),
name: '/system/common',
alwaysShow: true,
meta: { title: '通用管理', icon: 'lock' },
children: [
{
path: 'dict-info',
component: () => import('@/views/tt-server/system/common/dict-info/index'),
name: '/system/common/dict-info',
meta: { title: '字典管理', icon: 'edit' }
},
{
path: 'area-info',
component: () => import('@/views/tt-server/system/common/area-info/index'),
name: '/system/common/area-info',
meta: { title: '区域管理', icon: 'edit' }
},
{
path: 'system-param',
component: () => import('@/views/tt-server/system/common/system-param/index'),
name: '/system/common/system-param',
meta: { title: '系统参数', icon: 'edit' }
},
{
path: 'system-log',
component: () => import('@/views/tt-server/system/common/system-log/index'),
name: '/system/common/system-log',
meta: { title: '系统日志', icon: 'edit' }
}
]
}
]
}
]
后台数据设计:
表结构
CREATE TABLE `sys_menu` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '菜单主键',
`app_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '应用编号',
`menu_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单名称',
`menu_value` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单值',
`menu_icon` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单图标',
`menu_level` int NOT NULL DEFAULT '1' COMMENT '菜单层级',
`menu_type` varchar(12) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '菜单类型',
`menu_sort` int NOT NULL COMMENT '菜单排序',
`menu_route` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '菜单路由',
`is_show` tinyint(1) DEFAULT '1' COMMENT '是否展示 1展示 0隐藏',
`menu_path` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '菜单主键路径',
`parent_id` int NOT NULL DEFAULT '0' COMMENT '父级菜单,顶级菜单默认为0',
`creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`updater` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100200401 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统菜单表';
菜单记录:
【菜单路由】和【是否展示】是前端路由展示的判断条件
mysql> SELECT * FROM sys_menu;
+-----------+-----------+-----------+--------------+-----------+------------+-----------+-----------+-----------------------------+---------+---------------------------------+-----------+---------+---------------------+---------+---------------------+
| id | app_code | menu_name | menu_value | menu_icon | menu_level | menu_type | menu_sort | menu_route | is_show | menu_path | parent_id | creator | create_time | updater | update_time |
+-----------+-----------+-----------+--------------+-----------+------------+-----------+-----------+-----------------------------+---------+---------------------------------+-----------+---------+---------------------+---------+---------------------+
| 100000000 | tt-server | 系统管理 | system | | 1 | Directory | 1 | /system | 1 | 0,100000000 | 0 | admin | 2022-12-07 23:46:49 | admin | 2022-12-07 23:46:51 |
| 100100000 | tt-server | 权限维护 | privileges | | 2 | Directory | 1 | /system/rbac | 1 | 0,100000000,100100000 | 100000000 | admin | 2022-12-07 23:41:14 | admin | 2022-12-07 23:41:16 |
| 100100100 | tt-server | 用户管理 | user-info | | 3 | Function | 1 | /system/rbac/user-info | 1 | 0,100000000,100100000,100100100 | 100100000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100100200 | tt-server | 角色管理 | role-info | | 3 | Function | 2 | /system/rbac/role-info | 1 | 0,100000000,100100000,100100200 | 100100000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100100300 | tt-server | 菜单管理 | menu-info | | 3 | Function | 3 | /system/rbac/menu-info | 1 | 0,100000000,100100000,100100300 | 100100000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100100400 | tt-server | 权限管理 | permit-info | | 3 | Function | 4 | /system/rbac/privilege-info | 1 | 0,100000000,100100000,100100400 | 100100000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100200000 | tt-server | 通用管理 | common | | 2 | Directory | 2 | /system/common | 1 | 0,100000000,100200000 | 100000000 | admin | 2022-12-07 23:42:03 | admin | 2022-12-07 23:42:03 |
| 100200100 | tt-server | 字典管理 | dict-info | | 3 | Function | 1 | /system/common/dict-info | 1 | 0,100000000,100200000,100200100 | 100200000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100200200 | tt-server | 行政区域 | area-info | | 3 | Function | 2 | /system/common/area-info | 1 | 0,100000000,100200000,100200200 | 100200000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100200300 | tt-server | 系统参数 | system-param | | 3 | Function | 3 | /system/common/system-param | 1 | 0,100000000,100200000,100200300 | 100200000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
| 100200400 | tt-server | 系统日志 | system-log | | 3 | Function | 4 | /system/common/system-log | 1 | 0,100000000,100200000,100200400 | 100200000 | admin | 2022-12-07 23:44:12 | admin | 2022-12-07 23:44:12 |
+-----------+-----------+-----------+--------------+-----------+------------+-----------+-----------+-----------------------------+---------+---------------------------------+-----------+---------+---------------------+---------+---------------------+
展示效果
【Vue】 vue-element-admin 路由菜单配置的更多相关文章
- vue+npm+Element插件+路由
首先安装node.js 之后使用管理员输入命令 然后,就可以使用 npm 命令安装了: npm install -g @vue/cli安装完后,打开命令行窗口,会有一个 vue 命令:vue -v v ...
- Vue - 项目配置 ( element , 安装路由 , 创建路由 )
1,安装element : vue add element 2,安装路由 : vue add router 3,创建路由的过程 : (1) 新建 vu ...
- 【vue】iView-admin2.0动态菜单路由
vue项目实现动态路由有俩种方式 一.前端在routers中写好--所有--路由表 <前端控制路由>,登录时根据用户的角色权限来动态的显示菜单路由 二.前端通过调用接口请求拿到当前用户-- ...
- 【vue】iView-admin2.0动态菜单路由【版2】
依照iView-admin2.0动态菜单路由[版1] 归纳几个节点动态路由获取方式2 ——> easymock假数据 ——> 数据转组件处理.addRoutes ——> localS ...
- vue路由的配置
一.准备工作 1安装vue-cli npm install vue-cli -g 2检查是否安装成功 vue -V(大写V) 3初始化一个新的项目 vue init webpack vue-dem ...
- Vue 路由模块化配置
博客地址:https://ainyi.com/77 企业运营后台页面很多,路由如若不区分模块化配置,所有路由挤在同一个文件将不好维护,所以路由的配置也要模块化 分享两个解决方案 -- Vue 路由配置 ...
- vue项目中router路由配置
介绍 路由:控制组件之间的跳转,不会实现请求.不用页面刷新,直接跳转-切换组件>>> 安装 本地环境安装路由插件vue-router: cnpm install vue-rou ...
- Vue+elementUI 自定义动态数据菜单导航组件实现展开收缩+路由跳转router-view渲染数据 路由跳转到同一个页面带参数ID 自动刷新数据
准备:导入ElementUI 看官网教程 数据准备:JSON数据转换成树状 参考文章: JS实现 JSON扁平数据转换树状数据 后台我拿的数据是这样的格式: [ {id:1 , parentId: 0 ...
- 神奇!这款 Vue 后台框架居然不用手动配置路由
前言 做 Vue 开发脱离不了路由,尤其是中大型项目,页面多且杂,在配置路由的时候总是会变得逐渐暴躁,因为费时,并且又没有什么太多技术含量,总觉得是在浪费时间. 另外如果接手了别人的项目,当业务有变更 ...
- Vue路由相关配置
什么是路由? 1.在以前页面跳转使用的是超链接a标签或者js location.href,而路由是跳转切换组件的跳转方式 2.路由就是监听url的改变并提供相对应的组件用于展示 3.vue-route ...
随机推荐
- MySQL学习笔记-数据控制语言
SQL-数据控制语言(DCL) DCL语句用于管理数据库用户,控制数据库的访问权限 一. 管理用户 1. 查询用户 # 访问mysql数据库 use mysql; #查询user表 select * ...
- List<Map<String, Object>> 按照时间排序
// 准备一个集合 List<Map<String, Object>> resList= Lists.newArrayList(); Map<String, Object ...
- 『手撕Vue-CLI』自动安装依赖
开篇 经过『手撕Vue-CLI』拷贝模板,实现了自动下载并复制指定模板到目标目录.然而,虽然项目已复制,但其依赖并未自动安装,可能需要用户手动操作,这并不够智能. 正如前文所述,我们已经了解了业务需求 ...
- java读取txt文件行的两种方式对比
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import ja ...
- FreeRTOS简单内核实现3 任务管理
0.思考与回答 0.1.思考一 对于 Cotex-M4 内核的 MCU 在发生异常/中断时,哪些寄存器会自动入栈,哪些需要手动入栈? 会自动入栈的寄存器如下 R0 - R3:通用寄存器 R12:通用寄 ...
- Java JSON组成和解析
本框架JSON元素组成和分析,JsonElement分三大类型JsonArray,JsonObject,JsonString. JsonArray:数组和Collection子类,指定数组的话,使用A ...
- setsocket、getsocket 函数详解
背景 以前用到socket的时候会调用setsocket进行设置,现在整理有关的笔记的时候,重新查阅资料发现有点奇怪,发现大家比较少使用到这个. setsocket/getsocket #includ ...
- STM32 CubeMX 学习:003-定时器
背景 上一讲 STM32 CubeMX 学习:外部中断的使用 介绍了如何配置以及操作GPIO外部中断. 这一讲我们介绍定时器的有关概念,并对其中一种进行示范. HOST-OS : Windows-10 ...
- 一款利用人工智能将自然语言查询转换为 SQL 代码的互译工具 - SQL Translator
前言 对于后端程序员来说,编写SQL代码是日常工作中不可或缺的一部分.然而,随着数据复杂性的增加,如何高效.准确地编写SQL查询成为了新的挑战.幸运的是,SQL Translator的出现为后端程序员 ...
- 3562-Linux系统使用手册