最近,为了方便移动办公,我在开发 UniApp 的移动端后台管理系统。在开发过程中,我发现 UniApp 本身并不直接支持类似于 Ruoyi 的 v-hasPermi 自定义指令功能。本文将介绍如何在 UniApp 中实现类似 v-hasPermi 的自定义指令功能。
其实,这个过程本质上是将指令转化为 v-if,然后交由 uni() 处理。
1. 准备工作
首先,我们需要定义一个 permission.js 文件,该文件用于判断用户是否具有某个权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import {useAuthStore} from "@/store/auth";
const permission = (_BR) => {
const roles = useAuthStore().roles
if (_BR && typeof _BR === 'object' && _BR.length>0){ for (let i = 0; i < _BR.length; i++) { if(!roles.includes(_BR[i])) return false } return true } return false }
export default permission
|
可以直接引用该方法并传入权限字符串来判断用户是否有该权限
2. 全局引入 permission
接下来,在项目的 main.js 中将 permission 方法全局引入:
1 2 3 4 5 6 7 8 9 10 11 12
|
import { createSSRApp } from "vue" import App from "./App.vue" import permission from "@/permission" export function createApp() { const app = createSSRApp(App) app.config.globalProperties.$permission = permission return { app }; }
|
这样,你就可以在任何组件中通过 $permission 直接使用权限判断功能。
3.编写vite插件:
接下来,编写一个 Vite 插件来处理 cu-permission 属性,将其转化为 v-if。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
const rollupPermissionConverter = () => ({ name: 'rollup-permission-converter', transform(code, id) { if (id.endsWith('.vue')) { const regex = /v-if="(.+?)"\s+v-if="(.+?)"/g;
code = code.replace(/<[^>]+cu-permission="([^"]+)"[^>]*>/g, (match, cuPermissionValue) => { return match.replace(`cu-permission="${cuPermissionValue}"`, `v-if="$permission(${cuPermissionValue})"`); }) .replace(/<[^>]+v-if="([^"]+)"[^>]*v-if="([^"]+)"[^>]*>/g, (match, firstVIf, secondVIf) => { const mergedVIf = `${firstVIf} && ${secondVIf}`; return match.replace(/v-if="([^"]+)"/, `v-if="${mergedVIf}"`); }) .replace(regex, 'v-if="$1"'); } return code; }, });
export default rollupPermissionConverter;
|
通过这个插件,我们可以将页面中使用的 cu-permission 属性转换为 Vue 的 v-if 语句,从而实现权限控制。
4. 使用自定义指令
经过插件的处理后,可以在 Vue 组件中直接使用 cu-permission 属性进行权限控制:
示例1
1 2 3 4 5 6 7 8 9
| <template> <view v-if="showDetail" cu-permission="['system:a:b']"> ... </view> </template>
<script setup> const showDetail = ref(false); </script>
|
经过插件转译后,这段代码会变成:
1 2 3 4 5 6 7 8 9
| <template> <view v-if="showDetail && $permission(['system:a:b'])"> ... </view> </template>
<script setup> const showDetail = ref(false); </script>
|
示例2
1 2 3 4 5
| <template> <view cu-permission="['system:a:c']"> <scroll-view>...</scroll-view> </view> </template>
|
经过插件转译后,这段代码会变成:
1 2 3 4 5
| <template> <view v-if="$permission(['system:a:c'])"> <scroll-view>...</scroll-view> </view> </template>
|