夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 微前端

  • 权限控制

    • 前端实现权限控制
      • 业务背景
      • 原理
        • 权限分配
        • 技术实现
      • 动态路由
        • 基础路由
        • 动态路由
      • 控制按钮级权限
      • 遇到的问题
  • monorepo

  • 《前端架构》
  • 权限控制
夜猫子
2023-02-14
目录

前端实现权限控制

# 实现RBAC菜单按钮权限管理

# 业务背景

现在后台管理系统一般都会涉及到角色权限的分类,目的是为了使用一套系统多个角色,每个角色分配不同的菜单和按钮权限,进而对不同角色实现权限管理

# 原理

# 权限分配

1.建立数据源

  • 项目菜单的数据源
  • 功能按钮的数据源
  • 角色的数据源
  • 人员的数据源

2.把菜单和按钮相应的数据源分配给对应的角色

3.创建人员的时候选择对应的角色

4.用户登录之后即可获取对应的权限

# 技术实现

  • 动态路由(对菜单权限进行管理)
  • v-permission指令(将权限管理的颗粒度达到到按钮的级别)

# 动态路由

# 基础路由

首先肯定是要有一个登录等基础路由

// 页面静态路由(所有权限都一定会有的路由)
// 直接挂载
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
    // ... 可能还会有忘记密码,注册等页面路由
  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  }
]

const router = createRouter({
  history: createWebHashHistory(process.env.BASEURL),// 这里是hash缓存
  routes,
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 动态路由

登录成功后接口返回的用户对应能访问的动态路由。

主要通过两个函数实现。router.addRoute() 和 router.removeRoute()。

// 需要动态加载的路由
export const asyncRoutes = [
    ...
]
const asyncRouter=router.addRoutes(asyncRoutes) // 动态添加
// asyncRouter() 可以通过调用回调的方式删除路由
//或使用api: router.removeRoute('about') 其中 about 为路由名称
1
2
3
4
5
6
7

最终的路由可能是

[
  {
    path: '/user',
    component: () => import('@/layouts/UserLayout.vue'),
    redirect: '/user/login',
    children: [
      {
        path: 'login',
        name: 'login',
        component: () => import(/* webpackChunkName: "user" */ '@/views/login/Login.vue'),
      },
      {
        path: 'register',
        name: 'register',
        component: () => import(/* webpackChunkName: "user" */ '@/views/login/ResetPwd.vue'),
      }
    ],
  },
  {
    name: 'rootRouterIndex',
    path: '/',
    component: () => import('@/layouts/BasicLayout.vue'), // 主菜单
    redirect: '/xxx', // 可以在添加动态路由时通过 asyncRoutes[0].path 来添加默认的内容区,
    children: [动态路由]     
  },
  {
    path: '/404',
    component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404.vue'),
  },
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 控制按钮级权限

思路

给每一个按钮唯一标识,获取所有按钮权限进行逐个比对,有这个标识则显示,否则就不显示

示例

 <button
    v-permission="'base:soft:add'" // 唯一标识为 'base:soft:add'
    @click="handleAdd"
 >
  添加
</button>
1
2
3
4
5
6
  • 实现 v-permission 指令

v-permission 的作用就是动态添加或者移除按钮等元素

// directive.js
export const directives=(app)=>{
    const permissions = ["base:soft:add", "base:soft:cut"]
    app.directive('permission', (el, binding) => {
        const value = binding.value
        const isBind=Reflect.has(permissions, "*:*:*")||Reflect.has(permissions, value)
        if (!isBind) {
            el.parentNode && el.parentNode.removeChild(el)
          }
    })
}
1
2
3
4
5
6
7
8
9
10
11
// mian.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)

// 引入全局指令
import { directive } from './directive/directive'
 
// 全局注册
// 注意:要放在 const app = createApp(App) 之后
directive(app)
app.mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12

# 遇到的问题

使用addRoute添加动态路后,router.options的值是不会更新的,即无法获取添加后的完整的路由表。

  • 所以在获取到动态路由后需要将动态路由放到状态管理器中,方便后续 menu使用。
编辑 (opens new window)
上次更新: 2024/6/18 13:14:59
微前端
pnpm-workspace

← 微前端 pnpm-workspace→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式