vue3-封装权限按钮组件和自定义指令
“权限按钮组件”在中大型前端项目中是非常通用的一类功能组件,通常用于根据用户权限动态显示 CRUD 按钮(增删改查)。
下面设计一套:
- ✅ Vue 3 + TypeScript 写法
- ✅ 支持
v-permission或权限数组控制 - ✅ 封装单个 CRUD 按钮
- ✅ 提供组合按钮容器(任意组合增删改查)
- ✅ 支持统一样式、禁用态与事件透传
🧩 一、权限控制思路
假设你有一个权限系统,每个按钮对应一个权限码,例如:
"sys:user:add" // 新增
"sys:user:edit" // 修改
"sys:user:delete" // 删除
"sys:user:view" // 查询
用户登录后,存储在 userStore 中:
userStore.permissions = ['sys:user:view', 'sys:user:edit']
✅ 二、权限按钮指令(v-permission)
创建一个通用权限指令:
// directives/permission.ts
import { Directive } from "vue";
import { useUserStore } from "@/store/modules/user";export const permission: Directive = {mounted(el, binding) {const userStore = useUserStore();const requiredPerm = binding.value as string;if (!userStore.permissions.includes(requiredPerm)) {el.parentNode && el.parentNode.removeChild(el);}},
};
注册全局指令:
// main.ts
import { permission } from "@/directives/permission";
app.directive("permission", permission);
✅ 三、单个权限按钮组件
<!-- components/AuthButton.vue -->
<template><el-buttonv-if="hasPermission":type="type":icon="icon":disabled="disabled"@click="onClick"><slot>{{ label }}</slot></el-button>
</template><script setup lang="ts">
import { computed } from "vue";
import { useUserStore } from "@/store/modules/user";interface Props {/** 权限码,例如 sys:user:add */perm: string;/** 按钮文字 */label?: string;/** Element Plus 按钮类型 */type?: string;/** 图标 */icon?: string;/** 是否禁用 */disabled?: boolean;
}const props = defineProps<Props>();
const emit = defineEmits(["click"]);const userStore = useUserStore();// 权限校验
const hasPermission = computed(() =>userStore.permissions.includes(props.perm)
);const onClick = () => {emit("click");
};
</script>
✅ 四、CRUD 组合按钮组件
该组件可以自由组合 “增删改查” 四种按钮。
<!-- components/AuthCrudButtons.vue -->
<template><div class="auth-crud-buttons"><AuthButtonv-if="showAdd"perm="sys:user:add"type="primary"icon="Plus"label="新增"@click="$emit('add')"/><AuthButtonv-if="showEdit"perm="sys:user:edit"type="warning"icon="Edit"label="编辑"@click="$emit('edit')"/><AuthButtonv-if="showDelete"perm="sys:user:delete"type="danger"icon="Delete"label="删除"@click="$emit('delete')"/><AuthButtonv-if="showView"perm="sys:user:view"type="info"icon="View"label="查看"@click="$emit('view')"/></div>
</template><script setup lang="ts">
import AuthButton from "./AuthButton.vue";interface Props {/** 是否显示新增按钮 */showAdd?: boolean;/** 是否显示编辑按钮 */showEdit?: boolean;/** 是否显示删除按钮 */showDelete?: boolean;/** 是否显示查看按钮 */showView?: boolean;
}defineProps<Props>();
defineEmits(["add", "edit", "delete", "view"]);
</script><style scoped>
.auth-crud-buttons {display: flex;gap: 8px;
}
</style>
✅ 五、使用示例
✅ 单个按钮
<AuthButtonperm="sys:user:add"type="primary"label="新增"@click="handleAdd"
/>
若用户无
sys:user:add权限,则按钮不会渲染。
✅ 组合 CRUD 按钮
<AuthCrudButtons:show-add="true":show-edit="true":show-delete="true":show-view="false"@add="handleAdd"@edit="handleEdit"@delete="handleDelete"
/>
若用户只拥有
sys:user:view和sys:user:edit,则组件内部仅渲染“编辑”按钮。
✅ 六、进阶增强(推荐加上)
可以让 AuthCrudButtons 支持自定义权限码,让它在不同模块通用:
<script setup lang="ts">
import AuthButton from "./AuthButton.vue";interface Props {prefix?: string; // 例如 'sys:user'showAdd?: boolean;showEdit?: boolean;showDelete?: boolean;showView?: boolean;
}const props = defineProps<Props>();
defineEmits(["add", "edit", "delete", "view"]);const getPerm = (suffix: string) => `${props.prefix}:${suffix}`;
</script><template><div class="auth-crud-buttons"><AuthButtonv-if="showAdd":perm="getPerm('add')"type="primary"icon="Plus"label="新增"@click="$emit('add')"/><AuthButtonv-if="showEdit":perm="getPerm('edit')"type="warning"icon="Edit"label="编辑"@click="$emit('edit')"/><AuthButtonv-if="showDelete":perm="getPerm('delete')"type="danger"icon="Delete"label="删除"@click="$emit('delete')"/><AuthButtonv-if="showView":perm="getPerm('view')"type="info"icon="View"label="查看"@click="$emit('view')"/></div>
</template>
使用时:
<AuthCrudButtons prefix="sys:user" :show-add="true" :show-delete="true" />
✅ 七、总结
| 组件 | 作用 |
|---|---|
v-permission | 指令级权限控制 |
AuthButton | 单个按钮的权限封装 |
AuthCrudButtons | CRUD 按钮组合,可自由控制显示与模块前缀 |
