当前位置: 首页 > news >正文

【Vue框架】菜单栏权限的使用与显示

前言

在 【Vue框架】Vue路由配置 中的getters.js里,可以看到有一个应用程序的状态(变量)叫 permission_routes,这个就是管理前端菜单栏的状态。具体代码的介绍,都以注释的形式来说明。

1、modules\permission.js

1.1 代码

import { asyncRoutes, constantRoutes } from '@/router'/*** Use meta.role to determine if the current user has permission* @param roles 用户角色* @param route 路由信息*/
function hasPermission(roles, route) {// 判断route是否存在meta和meta.rolesif (route.meta && route.meta.roles) {// 判断当前传入的角色,是否存在路由的route中return roles.some(role => route.meta.roles.includes(role))} else {return true}
}/*** Filter asynchronous routing tables by recursion* 通过 递归 筛选异步路由表* 【将 基础路由(不含角色权限)和 符合用户权限的动态路由(需要角色权限)全部存入res】* @param routes asyncRoutes【去看router\index.js中asyncRoutes】* @param roles*/
export function filterAsyncRoutes(routes, roles) {const res = []// routes是在router\index.js定义的路由数组routes.forEach(route => {const tmp = { ...route } // 数组中遍历获取其中路由对象if (hasPermission(roles, tmp)) { // 判断当前路由是否存在角色if (tmp.children) { // 判断当前路由是否存在二级路由tmp.children = filterAsyncRoutes(tmp.children, roles)}res.push(tmp)}})return res
}// 定义的状态
const state = {routes: [],addRoutes: []
}// 用于存储一系列 改变 应用状态的方法
const mutations = {SET_ROUTES: (state, routes) => {state.addRoutes = routesstate.routes = constantRoutes.concat(routes) // 用户角色的动态路由加入到基础路由中}
}// 用于存储一系列 触发改变 应用状态的方法
const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {let accessedRoutesif (roles.includes('admin')) { // 如果roles数组中包含'admin'accessedRoutes = asyncRoutes || [] // 动态路由全部可以访问,如果asyncRoutes为`undefined`或`null`,则取[]} else {accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) // 递归出符合条件的路由}commit('SET_ROUTES', accessedRoutes)resolve(accessedRoutes)})}
}
// 默认导出一个对象,包含了模块的相关配置
export default {// 设置模块的命名空间为 `true`,这意味着该模块中的状态、mutations、getters、actions将被封装在命名空间中,以避免和其他模块的冲突namespaced: true,// 模块的状态state,// 模块的变化方法mutations,// 模块的行为方法(调用action,触发mutations,改变state)actions
}

该文件除了定义的routes路由状态和addRoutes动态添加的路由(后续用到的时候在提),主要在actions中定义了生成路由的行为方法generateRoutes,根据roles角色和内置传入的{ commit }context.commit)获取router\index.js中定义的一系列路由,简单说,就是在前端页面上被访问的路径

补充防忘记:

  1. new Promise()以及其参数
  2. 【Vue框架】Vue路由配置 看看路由
  3. 【Vue框架】Vuex状态管理

1.2 想法:

modules\permission.js中,根据generateRoutes提前写好的逻辑来判断查回用户的权限是否符合,这样不利于添加新角色的改动。
应该都得从数据库中查询,得到库中的角色和每个动态路由。(个人猜想,后续在尝试)

2、layout\components\Sidebar

2.1 index.vue

遍历展示整体的菜单栏。

<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' // 从`vuex`库中导入`mapGetters`函数,用于将getter映射到该组件的计算属性中
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'export default {// 在该组件中注册了`SidebarItem`和`Logo`两个组件,以便在模板中使用它们components: { SidebarItem, Logo },// `computed`计算属性中,可以定义一些依赖于其他数据的属性。这些属性的值会根据其依赖的数据动态计算得出,并在依赖数据发生变化时自动更新。// `computed`计算属性的定义方式可以是一个对象,对象的每个属性都是一个计算属性的定义// `...mapGetters([...])`将`mapGetters`返回的映射对象展开并添加到该组件的计算属性中,这样可以直接访问映射的getter// mapGetters([...])里的数组中包含想要映射的getter方法的名称computed: {...mapGetters(['permission_routes','sidebar']),// 根据当前路由对象的元信息(`meta`)中的`activeMenu`属性来确定活动的菜单项。// 如果未设置`activeMenu`属性,则返回当前路径(`path`)activeMenu() {const route = this.$route // `this.$route`是在Vue中访问当前路由的对象(全局属性,只读,不能直接更改路由信息)const { meta, path } = route// if set path, the sidebar will highlight the path you setif (meta.activeMenu) {return meta.activeMenu // 侧边栏将高亮显示设置的路径}return path // 如果未设置`activeMenu`属性,则返回当前路由的路径。侧边栏将根据当前路径高亮显示相应的菜单项},showLogo() {return this.$store.state.settings.sidebarLogo},variables() {return variables},isCollapse() {// 如果`opened`属性为`true`,则`isCollapse`为`false`,表示侧边栏未折叠;// 如果`opened`属性为`false`,则`isCollapse`为`true`,表示侧边栏已折叠return !this.sidebar.opened}}
}
</script>

2.2 SidebarItem.vue

具体遍历显示每一个具体的菜单项。

<template><div v-if="!item.hidden" class="menu-wrapper"><!-- 这的item就是route,onlyOneChild就是当前route下的子菜单 --><!-- 1判断route下是否为01个子菜单 && 2(!当前route下的子菜单是还存在子菜单||子菜单不存在时) &&  3--><!-- 这里的template:当前route下只有1个或0个子菜单,且唯一子菜单下不存在下级菜单时,执行这段代码效果:菜单栏中,该route为一级菜单,不显示其子菜单--><template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"><!-- 其子菜单中存在meta --><app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"><el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"><item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /></el-menu-item></app-link></template><!--  存在多级子菜单的时候  --><el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body><!-- 这里的插槽名为title;作用和上面一样,主要是显示一级菜单,但这里没用app-link让该菜单具有跳转功能 --><template slot="title"><item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /></template><!-- 具体的菜单项,遍历各个子菜单 --><sidebar-itemv-for="child in item.children":key="child.path":is-nest="true":item="child":base-path="resolvePath(child.path)"class="nest-menu"/></el-submenu></div>
</template><script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'export default {name: 'SidebarItem',components: { Item, AppLink },// 通过 `mixins` 可以将一些常用的选项(如 `data`、`methods`、`created` 等)或复杂逻辑封装成可复用的模块,并在多个组件中混入使用mixins: [FixiOSBug],// 用于定义组件的属性。可以是数组、对象或具体的属性定义。通过 props 可以接收组件外部传入的数据,并在组件内部使用props: {// route objectitem: {type: Object,required: true},isNest: {type: Boolean,default: false},basePath: {type: String,default: ''}},data() {// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237// TODO: refactor with render function// 当前route的子菜单this.onlyOneChild = nullreturn {}},methods: {hasOneShowingChild(children = [], parent) {const showingChildren = children.filter(item => {if (item.hidden) {return false} else {// Temp set(will be used if only has one showing child)this.onlyOneChild = itemreturn true}})// 只存在一个子菜单// When there is only one child router, the child router is displayed by defaultif (showingChildren.length === 1) {return true}// 不存在菜单// Show parent if there are no child router to displayif (showingChildren.length === 0) {// 如果没有子菜单显示,将父级菜单的一些属性复制到`onlyOneChild`对象中,同时设置`onlyOneChild`的`path`为空字符串,// 并设置`noShowingChildren`属性为`true`,表示没有子菜单显示。最后返回`true`。this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }return true}// 子菜单存在多个的时候return false},resolvePath(routePath) {// `isExternal(routePath)`函数判断`routePath`是否为外部链接,如果是外部链接,则直接返回`routePath`,不做处理// 当只有唯一子菜单时,`routePath`是子菜单路径if (isExternal(routePath)) {return routePath}// 当只有唯一子菜单时,`basePath`是父级菜单的路径if (isExternal(this.basePath)) {return this.basePath}// `path.resolve()`函数将`this.basePath`和`routePath`拼接成一个完整的路径,并返回该路径// 返回 `/父级菜单的路径/子菜单路径`return path.resolve(this.basePath, routePath)}}
}
</script>

2.3 Link.vue

<template><!-- eslint-disable vue/require-component-is --><component v-bind="linkProps(to)"><slot /></component>
</template><script>
import { isExternal } from '@/utils/validate'export default {props: {to: {type: String,required: true}},methods: {linkProps(url) {if (isExternal(url)) {return {is: 'a', // 标签名href: url, // 链接target: '_blank', // 用于指定链接在哪个窗口或框架中打开,`_blank`在新的标签页中打开链接rel: 'noopener' // 用于指定链接与当前页面之间的关系,当使用`target="_blank"`时,防止新打开的窗口通过`window.opener`属性访问到当前页面的信息,提高安全性。}}return {is: 'router-link', // 标签名to: url}}}
}
</script>

相关文章:

【Vue框架】菜单栏权限的使用与显示

前言 在 【Vue框架】Vue路由配置 中的getters.js里&#xff0c;可以看到有一个应用程序的状态&#xff08;变量&#xff09;叫 permission_routes&#xff0c;这个就是管理前端菜单栏的状态。具体代码的介绍&#xff0c;都以注释的形式来说明。 1、modules\permission.js 1…...

案例研究|大福中国通过JumpServer满足等保合规和资产管理双重需求

“大福中国为了满足安全合规要求引入堡垒机产品&#xff0c;在对比了传统型堡垒机后&#xff0c;发现JumpServer使用部署更加灵活&#xff0c;功能特性丰富&#xff0c;能够较好地满足公司在等保合规和资产管理方面的双重需求。” ——大福&#xff08;中国&#xff09;有限公…...

大数据课程I4——Kafka的零拷贝技术

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握Kafka的零拷贝技术&#xff1b; ⚪ 了解常规的文件传输过程&#xff1b; 一、常规的网络传输原理 表面上一个很简单的网络文件输出的过程&#xff0c;在OS底层&…...

红日ATT&CK VulnStack靶场(三)

网络拓扑 web阶段 1.扫描DMZ机器端口 2.进行ssh和3306爆破无果后访问web服务 3.已知目标是Joomla&#xff0c;扫描目录 4.有用的目录分别为1.php 5.configuration.php~中泄露了数据库密码 6.administrator为后台登录地址 7.直接连接mysql 8.找到管理员表&#xff0c;密码加密了…...

JavaScript之BOM+window对象+定时器+location,navigator,history对象

一.BOM概述 BOM即浏览器对象模型,它提供了独立于内容而与窗口进行交互的对象 BOM的顶级对象是window 二.window对象的常见事件 1.窗口加载事件window.onload window.onload function(){} 或者 window.addEventListener("onload" , function(){}); window.onlo…...

为MySQL新增一张performance_schema表 | StoneDB 技术分享会 #4

StoneDB开源地址 https://github.com/stoneatom/stonedb 设计&#xff1a;小艾 审核&#xff1a;丁奇、李浩 编辑&#xff1a;宇亭 作者&#xff1a;王若添 中国科学技术大学-软件工程-在读硕士、StoneDB 内核研发实习生 performance_schema 简介 MySQL 启动后会自动创建四…...

2023/8/12总结

增加了管理员功能点&#xff1a;&#xff08;管理标签和分类&#xff09; 另外加了一个转换成pdf的功能 主要是通过wkhtmltopdf实现的&#xff0c;之前看过很多说用adobe的还有其他但是都没成功。 然后就是在学习websocket和协同过滤算法实现&#xff0c;还只是初步了解了这些。…...

win10电脑npm run dev报错解决

npm run dev报错解决 出现错误前的操作步骤错误日志解决步骤 出现错误前的操作步骤 初始化Vue项目 $ npm create vue3.6.1创建项目文件夹client Vue.js - The Progressive JavaScript Framework✔ Project name: › client ✔ Add TypeScript? › No ✔ Add JSX Support? …...

如何使用PHP编写爬虫程序

在互联网时代&#xff0c;信息就像一条无休无止的河流&#xff0c;源源不断地涌出来。有时候我们需要从Web上抓取一些数据&#xff0c;以便分析或者做其他用途。这时候&#xff0c;爬虫程序就显得尤为重要。爬虫程序&#xff0c;顾名思义&#xff0c;就是用来自动化地获取Web页…...

分布式 - 服务器Nginx:一小时入门系列之HTTP反向代理

文章目录 1. 正向代理和反向代理2. 配置代理服务3. proxy_pass 命令解析4. 设置代理请求headers 1. 正向代理和反向代理 正向代理是客户端通过代理服务器访问互联网资源的方式。在这种情况下&#xff0c;客户端向代理服务器发送请求&#xff0c;代理服务器再向互联网上的服务器…...

Android Fragment (详细版)

经典好文推荐,通过阅读本文,您将收获以下知识点: 一、Fragment 简介 二、Fragment的设计原理 三、Fragment 生命周期 四、Fragment 在Activity中的使用方法 五、动态添加Fragment到Activity的方法 六、Activity 中获取Fragment 七、Fragment 获取宿主Activity的方法 八、两个…...

如何使用Flask-RESTPlus构建强大的API

如何使用Flask-RESTPlus构建强大的API 引言&#xff1a; 在Web开发中&#xff0c;构建API&#xff08;应用程序接口&#xff09;是非常常见和重要的。API是一种允许不同应用程序之间交互的方式&#xff0c;它定义了如何请求和响应数据的规范。Flask-RESTPlus是一个基于Flask的…...

UGUI事件系统EventSystem

一. 事件系统概述 Unity的事件系统具有通过鼠标、键盘、游戏控制柄、触摸操作等输入方式&#xff0c;将事件发送给对象的功能。事件系统通过场景中EventSystem对象的组件EventSystem和Standalone Input Module发挥功能。EventSystem对象通常实在创建画布的同时被创建的&#xf…...

redis学习笔记(三)

文章目录 key操作&#xff08;1&#xff09;查找键&#xff08;2&#xff09;判断键是否存在&#xff08;3&#xff09;查看键的的值的数据类型&#xff08;4&#xff09;删除键以及键对应的值&#xff08;5&#xff09;查看键的有效期&#xff08;6&#xff09;设置key的有效期…...

Go语言template模板语法

Go语言模板语法 文章目录 <center> Go语言模板语法连接前后端的符号: {{}}注释管道(pipeline)变量条件判断range 关键字with 关键字比较函数自定义函数嵌套模板模板继承 连接前后端的符号: {{}} 模板语法都包含在{{}}之中,其中{{.}}中的.表示当前对象.在传入一个结构体对…...

Python-OpenCV中的图像处理-物体跟踪

Python-OpenCV中的图像处理-物体跟踪 物体跟踪 物体跟踪 现在我们知道怎样将一幅图像从 BGR 转换到 HSV 了&#xff0c;我们可以利用这一点来提取带有某个特定颜色的物体。在 HSV 颜色空间中要比在 BGR 空间中更容易表示一个特定颜色。在我们的程序中&#xff0c;我们要提取的…...

本地Linux 部署 Dashy 并远程访问教程

文章目录 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 转载自cpolar极点云文章&#xff1a;本地Linux 部署 Dashy 并远程访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你…...

6.2 口令破解攻击

数据参考&#xff1a;CISP官方 目录 口令安全问题口令破解攻击口令破解安全防护口令使用安全管理 一、口令安全问题 什么是口令 身份验证的机制&#xff0c;俗称 “密码"&#xff0c;对应英文单词为 password成本较低&#xff0c;得到广泛应用信息安全中的 “密码”…...

SSL账号申请及配置

摘自个人印象笔记https://app.yinxiang.com/fx/db244155-c858-4d8a-93a8-08071d168dc8ssl申请平台&#xff1a;https://blog.freessl.cn/ ajian51168qq.com … 操作说明&#xff1a;https://blog.freessl.cn/acme-quick-start/ nginx配置&#xff1a; upstream local_tomcat{s…...

JS代码混淆加密有什么用?

JS加密、JS混淆&#xff0c;有这些用&#xff1a; 1、前端JS代码&#xff0c;如果不加密&#xff0c;它人可以随便copy、任意修改。自己写的代码&#xff0c;可以轻易成为别人的成果。 对JS代码混淆加密&#xff0c;则可以防止这种他人随意白嫖的问题&#xff0c;代码是自己辛…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...