VUE 自定义指令实现按钮级权限

132 阅读2分钟

本文仅讨论按钮权限,页面菜单即路由权限需另行配置。

前提

  • 系统需要以更小粒度的控制划分权限时;
  • 在系统权限配置的地方,需要渲染可以配置到操作按钮的权限树,权限树层级与页面层级对应;
  • 根据整个权限树的权限标识,声明一个常量对象与权限树层级及标识对应,权限标识跟后台接口对应;
  • 登录系统时,可从登录接口获取当前角色对应的权限标识列表,存在本地即可;

配置

  • 自定义指令
// directive/permission.ts
import { getStorage } from '@/utils/storage.ts';
import type { App } from 'vue';

export default {
    install(app: App) {
        /**
         * @description 注册全局指令
         * @params { string } name 指令名
         * @params { Function | Object } definition 具有7个生命周期
         */
        app.directive('permission', {
            /**
             * @description 指令是具有一组生命周期的钩子,钩子函数的有3-4个参数,如下:
             * @param el 指令绑定到的元素,这可用于直接操作 DOM。
             * @param binding 一个对象包含一些属性,binding.value 是传递给指令的值。
             * @param vnode 代表绑定元素的底层 VNode。
             * @param prevNode 之前的渲染中代表指令所绑定元素的 VNode,仅在 beforeUpdate 和 updated 钩子中可用。
             */
            mounted(el, binding) {
                // getStorage 封装方法:获取 localStorage 中的信息
                const permissions: string[] = getStorage('pcPerms') || [];
                if (!binding.value.some((permission: string) => permissions.includes(permission))) {
                    el.style.display = 'none';
                }
            },

            updated(el, binding) {
                const permissions: string[] = getStorage('pcPerms') || [];
                if (!binding.value.some((permission: string) => permissions.includes(permission))) {
                    el.style.display = 'none';
                } else {
                    el.style.display = '';
                }
            },
        });
    },
};
  • 全局注册指令
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import permission from '@/directive/permission';

(async () => {
    // 创建 app 实例
    const app = createApp(App);

    // 全局注册指令
    app.use(permission);

    app.mount('#app');
})();
  • 权限树常量对象
// constant/permission.ts
export const PERMISSION = {
    /**
     * 基础数据
     */
    BASIC_DATA: {
        /**主数据*/
        MASTER_DATA: {
            /**列表*/
            USER_LIST: {
                /**查询*/
                QUERY: 'user:select',
                /**新增 编辑*/
                EDIT: 'user:insert',
                /**删除 */
                DELETE: 'user:delete',
                /**导入 */
                IMPORT: 'user:import',
                /**导出 */
                EXPORT: 'user:export',
            },
            // ...
        }
        // ...
    }
    // ...
} 
  • 页面应用
import { PERMISSION } from '@/constant/permission';
<el-button v-permission="[PERMISSION.BASIC_DATA.MASTER_DATA.USER_LIST.EDIT]">
    新增
</el-button>