【Vue3+Ts项目】硅谷甄选 — 菜单权限+按钮权限

2024-01-19 17:04

本文主要是介绍【Vue3+Ts项目】硅谷甄选 — 菜单权限+按钮权限,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、菜单权限

1.1 路由拆分 

 将项目路由拆分为:

  • 静态路由:login、404、home、screen
  • 异步路由:权限管理(包含三个子路由)、商品管理(包含四个子路由)
  • 任意路由:任意路由

 src/router/routes.ts

// 对外暴露配置路由(常量路由):全部用户都可以访问到的路由
export const constantRoute = [{// 登录path: '/login',component: () => import('@/views/login/index.vue'),name: 'login',meta: {title: '登录', // 菜单标题hidden: true, // 代表路由标题在菜单中是否隐藏  true:隐藏  false:显示icon: 'Promotion', // 菜单文字左侧的图标,支持element-plus全部图标},},{// 登录成功以后展示数据的路由path: '/',component: () => import('@/layout/index.vue'),name: 'layout',meta: {title: '',hidden: true,icon: '',},redirect: '/home',children: [{path: '/home',component: () => import('@/views/home/index.vue'),name: 'home',meta: {title: '首页',hidden: false,icon: 'HomeFilled',},},],},{// 404path: '/404',component: () => import('@/views/404/index.vue'),name: '404',meta: {title: '404',hidden: true,icon: 'BrushFilled',},},{path: '/screen',component: () => import('@/views/screen/index.vue'),name: 'Screen',meta: {title: '数据大屏',hidden: false,icon: 'Platform',},}
]//异步路由
export const asnycRoute = [{path: '/acl',component: () => import('@/layout/index.vue'),name: 'Acl',meta: {title: '权限管理',icon: 'Lock',},redirect: '/acl/user',children: [{path: '/acl/user',component: () => import('@/views/acl/user/index.vue'),name: 'User',meta: {title: '用户管理',icon: 'User',},},{path: '/acl/role',component: () => import('@/views/acl/role/index.vue'),name: 'Role',meta: {title: '角色管理',icon: 'UserFilled',},},{path: '/acl/permission',component: () => import('@/views/acl/permission/index.vue'),name: 'Permission',meta: {title: '菜单管理',icon: 'Monitor',},},],},{path: '/product',component: () => import('@/layout/index.vue'),name: 'Product',meta: {title: '商品管理',icon: 'Goods',},redirect: '/product/trademark',children: [{path: '/product/trademark',component: () => import('@/views/product/trademark/index.vue'),name: 'Trademark',meta: {title: '品牌管理',icon: 'ShoppingCartFull',},},{path: '/product/attr',component: () => import('@/views/product/attr/index.vue'),name: 'Attr',meta: {title: '属性管理',icon: 'ChromeFilled',},},{path: '/product/spu',component: () => import('@/views/product/spu/index.vue'),name: 'Spu',meta: {title: 'SPU管理',icon: 'Calendar',},},{path: '/product/sku',component: () => import('@/views/product/sku/index.vue'),name: 'Sku',meta: {title: 'SKU管理',icon: 'Orange',},},],},
]//任意路由
export const anyRoute = {// 任意路由path: '/:pathMatch(.*)*',redirect: '/404',name: 'Any',meta: {title: '任意路由',hidden: true,icon: 'Wallet',},
}

1.2  菜单权限业务实现 

 PS:退出登录记得删除添加的路由,防止切换角色后还能访问另一个角色的权限

src/store/modules/user.ts

......
// 引入路由(常量路由)
import { constantRoute, asnycRoute, anyRoute } from '@/router/routes'// 引入深拷贝方法
//@ts-expect-error
import cloneDeep from 'lodash/cloneDeep'
import router from '@/router'
// 用于过滤当前用户需要展示的异步路由
function filterAsyncRoute(asnycRoute: any, routes: any) {return asnycRoute.filter((item: any) => {if (routes.includes(item.name)) {if (item.children && item.children.length > 0) {item.children = filterAsyncRoute(item.children, routes)}return true}})
}
......const useUserStore = defineStore('User', {// 小仓库存储数据的地方state: (): UserState => {return {......menuRoutes: constantRoute, // 仓库存储生成菜单需要数组(路由)   removeRouteCallbackList: []}},// 异步|逻辑的地方actions: {......// 获取用户信息async userInfo() {// 获取用户信息进行存储仓库当中(用户头像、名字)let result: userInfoResponeData = await reqUserInfo()// 如果获取信息成功,存储下用户信息if (result.code === 200) {this.username = result.data.namethis.avatar = result.data.avatar// 计算当前用户需要展示的异步路由const userAsyncRoute = filterAsyncRoute(cloneDeep(asnycRoute),result.data.routes)// 菜单需要的数据整理完毕this.menuRoutes = [...constantRoute, ...userAsyncRoute, anyRoute]// 目前路由器管理的只有常量路由:用户计算完毕异步路由、任意路由动态追加;[...userAsyncRoute, anyRoute].forEach((route: any) => {let removeRoute = router.addRoute(route)this.removeRouteCallbackList.push(removeRoute)})return 'ok'} else {return Promise.reject(new Error(result.message))}},// 退出登录async userLogout() {let result: any = await reqLogout()if (result.code === 200) {// 目前没有mock接口:退出登录接口(通知服务器本地用户唯一标识失败)this.token = ''this.username = ''this.avatar = ''REMOVE_TOKEN()// 退出登录时删除登录添加的路由this.removeRouteCallbackList.forEach((removeRouteCallback: any) => {removeRouteCallback()})return 'ok'} else {return Promise.reject(new Error(result.message))}},},getters: {},
})

刷新的时候是异步路由,有可能获取到用户信息,异步路由还没有加载完毕,出现空白的效果!!

解决方法:在全局前置守卫中,获取用户信息后改成next({...to})

  • next() :直接放行(这种写法会导致刷新产生空白的效果)
  • next({...to}):等待路由加载完毕再放行

src/permission.ts

......try {// 获取用户信息await useStore.userInfo()// 放行//等待路由加载完毕再放行next({ ...to})} catch (error) {}.......

 二、按钮权限

1.1 按钮权限业务实现 

1.1.1 用户按钮权限信息存储

src/store/modules/user.ts 

......
state: (): UserState => {return {......//存储当前用户是否包含某一个按钮buttons: [],}
......
async userInfo() {......// 如果获取信息成功,存储下用户信息if (result.code === 200) {......this.buttons = result.data.buttons......}

 1.1.2 定义全局自定义指令

src/directive/has.ts 

import pinia from "@/store"
import useUserStore from "@/store/modules/user"
const userStore = useUserStore(pinia)
export const isHasButton = (app: any) => {// 获取对应的用户仓库// 全局自定义指令:实现按钮的权限app.directive('has', {// 代表使用这个全局指令的DOM|组件挂载完毕的时候会执行一次mounted(el: any, options: any) {// 自定义指令右侧的数值:如果在用户信息buttons数组中没有// 从DOM树上干掉if (!userStore.buttons.includes(options.value)) {el.parentNode.removeChild(el)}},})
}

 在main.ts文件中引入自定义指令文件

// 引入自定义指令文件
import { isHasButton } from '@/directive/has'
isHasButton(app)

 1.1.3 使用自定义指令配置按钮权限

PS:此处以其中一个按钮作为例子,项目中其他按钮的权限都需要配置

<el-button type="primary" size="default" icon="Plus" @click="addTrademark" v-has="'btn.Trademark.add'">

这篇关于【Vue3+Ts项目】硅谷甄选 — 菜单权限+按钮权限的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/623089

相关文章

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

如何在Spring Boot项目中集成MQTT协议

《如何在SpringBoot项目中集成MQTT协议》本文介绍在SpringBoot中集成MQTT的步骤,包括安装Broker、添加EclipsePaho依赖、配置连接参数、实现消息发布订阅、测试接口... 目录1. 准备工作2. 引入依赖3. 配置MQTT连接4. 创建MQTT配置类5. 实现消息发布与订阅

springboot项目打jar制作成镜像并指定配置文件位置方式

《springboot项目打jar制作成镜像并指定配置文件位置方式》:本文主要介绍springboot项目打jar制作成镜像并指定配置文件位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录一、上传jar到服务器二、编写dockerfile三、新建对应配置文件所存放的数据卷目录四、将配置文

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

怎么用idea创建一个SpringBoot项目

《怎么用idea创建一个SpringBoot项目》本文介绍了在IDEA中创建SpringBoot项目的步骤,包括环境准备(JDK1.8+、Maven3.2.5+)、使用SpringInitializr... 目录如何在idea中创建一个SpringBoot项目环境准备1.1打开IDEA,点击New新建一个项

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled