vue3+ts项目使用自定义指令实现根据角色权限控制显示隐藏

  1. 在src目录下新建directives文件夹,然后在文件夹中新建一个permission.ts文件,代码如下
import session from '@/utils/session';
import type { ObjectDirective } from 'vue';

const userInfo = session.get('userInfo');

const getRole = () => {
  if (userInfo && userInfo.userAuths && userInfo.userAuths[0] && userInfo.userAuths[0].roleId) {
    return userInfo.userAuths[0].roleId;
  }
  return '';
};
//处理角色权限的代码
const permission: ObjectDirective = {
  mounted(el: any, binding: any) {
    const { value } = binding;
    const role = getRole();
    if (value && value instanceof Array && value.length > 0) {
      const permissionRoles = value;
      const hasPermission = permissionRoles.includes(role);
      if (!hasPermission) {
        // eslint-disable-next-line no-unused-expressions
        el.parentNode && el.parentNode.removeChild(el);
      }
    } else {
      throw new Error('need roles! Like v-permission="["admin","editor"]"');
    }
  },
};

export default permission;

  1. 在需要使用该指令的文件夹中引入使用
<template>

          <el-button
            v-permission="['admin']"
          </el-button>

</template>

<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, Ref, ref, unref } from "vue";

import permission from "@/directives/permission";

export default defineComponent({

  name: "Examine",
  directives: {
    permission
  },
  components: {
  },
  setup() {
  }
});
</script>
<style scoped lang="scss">
</style>

### 关于 Vue 3 和 TypeScript 结合实现 RBAC 的方案 #### 项目结构设计 为了更好地管理和维护代码,在构建基于 Vue 3 和 TypeScript 的 RBAC 应用程序时,合理的文件夹布局至关重要。通常情况下,应用程序可以按照功能模块来划分目录: - `src/`:项目的根目录。 - `assets/`: 存放静态资源文件,比如图片、样式表等。 - `components/`: 组件库所在位置,用于存放可复用的 UI 组件。 - 可进一步细分为公共组件(如按钮、输入框)、业务逻辑相关联的具体页面组件等子文件夹。 - `router/`: 定义路由配置的地方,负责处理不同 URL 对应的内容展示规则。 - `store/`: 如果采用 Vuex 或 Pinia 进行状态管理,则此为存储全局共享数据的位置;对于本案例而言,建议使用 Pinia[^1]。 - `views/`: 放置各个视图级别的大型单页应用(SPA),即所谓的“页面”,每个页面可能由多个小型组件构成。 - `services/`: API 请求服务层,封装 HTTP 调用来简化前端与其他系统的交互过程。 - `utils/`: 工具方法集合区,放置那些不涉及具体业务但是会被广泛使用的辅助函数。 ```typescript // src/router/index.ts import { createRouter, createWebHistory } from &#39;vue-router&#39; import HomeView from &#39;../views/Home.vue&#39; const routes = [ { path: &#39;/&#39;, name: &#39;home&#39;, component: HomeView, meta: { requiresAuth: true }, // 添加元信息字段表示该路径需要认证 }, ] const router = createRouter({ history: createWebHistory(), routes, }) export default router; ``` #### 权限管理体系搭建 RBAC的核心在于定义角色及其关联权限,并据此决定用户能否执行特定操作或访问某些资源。以下是利用 Vue Router 配合自定义指令的方式来进行简单的权限验证机制的设计思路: ##### 创建权限判断工具函数 编写一个名为 `auth.js` 的 JavaScript 文件作为权限校验器,它可以根据当前用户的登录状态以及所拥有的角色列表去匹配目标地址所需的最低限度的角色等级。 ```javascript // src/utils/auth.js function hasPermission(roles, routeMetaRoles) { if (routeMetaRoles && routeMetaRoles.length > 0) { return roles.some(role => routeMetaRoles.includes(role)); } return false; } export function checkRoutePermissions(to, from, next, store) { const userRoles = store.state.user.roles || []; const requiredRole = to.meta.requiresAuth; if (!requiredRole || !Array.isArray(requiredRole)) { return next(); } if (hasPermission(userRoles, requiredRole)) { return next(); } else { alert(&#39;您没有足够的权限&#39;); return next({name:&#39;login&#39;}); } } ``` ##### 初始化导航守卫并集成权限检测 在应用启动之初设置好前置钩子(pre-route guards),每当发生跳转事件之前都会触发这些回调函数从而完成必要的安全检查工作。 ```typescript // main.ts import { createApp } from &#39;vue&#39;; import App from &#39;./App.vue&#39;; import router from &#39;./router&#39;; import pinia from &#39;./stores&#39;; // 使用Pinia替代Vuex进行状态管理 import { checkRoutePermissions } from &#39;@/utils/auth&#39;; createApp(App).use(pinia).use(router); router.beforeEach((to, _, next) => { checkRoutePermissions(to, null as any, next, useUserStore()); }); new createApp(App).mount(&#39;#app&#39;); ``` ##### 自定义指令增强元素级权限控制 除了页面级别外,还可以针对具体的 HTML DOM 元素实施更精细粒度的安全策略——只允许拥有相应授权的人看到指定的操作按钮或其他控件。这可以通过创建一个新的 v-permission 指令轻松达成目的。 ```typescript // directives/permission.ts import type { DirectiveBinding } from "vue"; export default { mounted(el: HTMLElement, binding: DirectiveBinding<string[]>) { const value = Array.isArray(binding.value)?binding.value:[]; const userRoles = JSON.parse(localStorage.getItem(&#39;user_roles&#39;)||&#39;[]&#39;); if(!value.every(v=>userRoles.indexOf(v)>-1)){ el.parentNode?.removeChild(el); } } }; ``` 然后可以在模板里像这样使用新注册好的属性: ```html <button v-permission="[&#39;admin&#39;]">删除</button> <!-- 上述代码意味着只有当用户的role包含"admin"的时候才会显示这个按钮 --> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值