所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

Vue3封装全局自定义指令|按钮权限控制功能保姆级实例教程

Vue3封装全局自定义指令|按钮权限控制功能保姆级实例教程 一

文章目录CloseOpen

本文将以“保姆级”步骤带大家实现这一功能:从理解需求(根据用户权限列表隐藏/禁用按钮),到封装全局自定义指令的完整流程(指令注册、权限校验逻辑编写、参数传递),再到实际项目中的使用实例(按钮绑定指令并传入权限标识)。还会覆盖动态权限更新、边界情况处理等细节,即使是Vue3新手也能跟着完成按钮权限的精准控制,最终用最简代码实现灵活、可维护的按钮权限管理方案。

你有没有过这种情况?做后台管理系统时,不同角色的按钮要藏要显,要么每个按钮都写v-if判断权限,要么写一堆重复的逻辑,改权限的时候得一个个文件找,累得要命?我去年帮朋友做电商后台时就踩过这坑——当时用v-if写了20多个按钮的权限,后来客户要加新角色,我熬夜改了3小时才弄完,差点没崩溃。后来我发现用Vue3全局自定义指令能解决这事儿,一次封装全项目能用,现在再做权限控制,10分钟就能搞定新需求。

为什么选Vue3全局自定义指令?不是v-if不好,是它不够“灵活”

为什么不用v-if反而用自定义指令?我刚开始也纳闷,直到试了才明白——v-if是直接不渲染按钮,但有时候我们需要按钮在那但不能点(比如禁用状态),或者隐藏的时候给个提示,v-if就做不到这么细。而且全局指令的好处是,你在main.js里注册一次,所有组件都能用,不用每个组件都import或者写重复的判断函数。就像你有个万能钥匙,开所有门都能用,不用带一串钥匙。

再说Vue3的自定义指令本身——它是专门用来操作DOM的,比如你想给按钮加个禁用状态,或者改个样式,用指令比用v-if方便多了。Vue3的自定义指令有几个生命周期钩子,最常用的是mounted(DOM挂载后)和updated(组件更新时)——这俩钩子能让我们在按钮渲染出来后,检查用户的权限,如果没权限就隐藏或者禁用。比如mounted的时候,我们拿到用户的权限列表,和按钮需要的权限对比,没权限就给按钮加个display: none,或者设置disabled属性;updated的时候,要是用户权限变了(比如切换角色),再重新检查一次,就能更新按钮的状态。

我之前做过个对比,用v-if和用自定义指令处理10个按钮的权限:用v-if要写10次重复的判断逻辑,每个组件都得引store里的权限列表;用自定义指令只需要写一次逻辑,全局注册后,所有按钮只要加个v-permission指令就行。后来我把这个对比做成了表格,你看了就更清楚:

对比项 v-if 自定义指令
复用性 低,需重复写判断逻辑 高,全局注册一次全项目用
灵活性 仅能控制渲染与否 可控制隐藏、禁用、提示等
维护成本 高,改权限需改多个组件 低,改指令逻辑一次生效

Vue3官方文档里也说,自定义指令是“对普通DOM元素进行底层操作的主要方式”——这正好戳中了权限控制的需求:我们需要直接操作按钮的DOM,比如隐藏、禁用,而不是仅仅控制它是否渲染。

手把手教你封装:从0到1做个能复用的权限指令

说了这么多,直接上干货——我把封装步骤拆成了4步,每一步都带代码,你跟着做就行。

第一步:先搞定权限判断的“核心逻辑”

你得有个地方存用户的权限列表——比如用Pinia或者Vuex存,比如store里的state.user.userPermissions,是个数组,比如['add-user', 'edit-user', 'delete-user']

然后写个权限判断函数,比如在utils/permission.js里:

// utils/permission.js

import { useUserStore } from '@/store/user'; // 假设用Pinia存用户信息

export function checkPermission(requiredPerms) {

const userStore = useUserStore();

const userPerms = userStore.userPermissions || []; // 防止userPerms为undefined

// 判断是单个权限还是多个权限

if (Array.isArray(requiredPerms)) {

// 多个权限:需要全部满足(用every),如果要满足其中一个用some

return requiredPerms.every(perm => userPerms.includes(perm));

} else {

// 单个权限:直接判断是否包含

return userPerms.includes(requiredPerms);

}

}

这里要注意两点:一是要处理userPermsundefined的情况,不然会报错;二是支持单个权限(字符串)和多个权限(数组)的判断——我之前做项目时遇到过需要多个权限的情况,当时没处理数组,结果按钮一直显示不出来,后来加了数组判断才好。

第二步:写指令的“ DOM 操作逻辑”

接下来封装自定义指令,比如在directives/permission.js里:

// directives/permission.js

import { checkPermission } from '@/utils/permission';

export const permissionDirective = {

// DOM挂载后执行(第一次渲染时)

mounted(el, binding) {

const requiredPerms = binding.value; // 从指令参数里拿需要的权限

if (!checkPermission(requiredPerms)) {

// 没权限的处理:隐藏或者禁用,选一个就行

// 选项1:隐藏按钮

el.style.display = 'none';

// 选项2:禁用按钮并加提示

// el.disabled = true;

// el.title = '您没有操作权限';

}

},

// 组件更新时执行(比如用户切换角色,权限变化)

updated(el, binding) {

const requiredPerms = binding.value;

const hasPerm = checkPermission(requiredPerms);

if (hasPerm) {

// 有权限:恢复显示/启用

el.style.display = ''; // 清空display属性,用默认样式

// el.disabled = false;

// el.title = '';

} else {

// 没权限:隐藏/禁用

el.style.display = 'none';

// el.disabled = true;

// el.title = '您没有操作权限';

}

}

};

这里的关键是updated钩子——我之前漏过这个钩子,结果用户切换角色后,权限变了但按钮状态没更,后来加上updated,问题直接解决。比如用户原本是普通用户,没add-user权限,按钮隐藏;切换到管理员后,userPermissions里有了add-userupdated钩子触发,按钮就显示出来了,完全不用刷新页面。

第三步:全局注册,让所有组件都能用

写好指令后,在main.js(或main.ts)里注册:

// main.js

import { createApp } from 'vue';

import App from './App.vue';

import { permissionDirective } from '@/directives/permission';

const app = createApp(App);

// 全局注册自定义指令

app.directive('permission', permissionDirective);

app.mount('#app');

就这么一行代码,所有组件都能用上v-permission指令了——是不是比每个组件都写v-if方便多了?

第四步:项目里用起来,比v-if还简单

现在到组件里用指令,比如在UserList.vue里:

<!-
  • UserList.vue >
  • <!-

  • 单个权限:需要add-user权限 >
  • 新增用户

    <!-

  • 多个权限:需要add-user和edit-user都有 >
  • 编辑用户

    <!-

  • 禁用状态的例子:没权限时禁用而不隐藏 >
  • 删除用户

    如果要改没权限时的处理方式,比如把隐藏改成禁用,直接改directives/permission.js里的逻辑就行——比如把el.style.display = 'none'改成el.disabled = true,再加个title提示,所有用这个指令的按钮都会生效,不用一个个组件改。

    那些容易踩的“坑”,我帮你避了

    最后说几个我踩过的坑,你注意别犯:

  • 没处理binding.value的类型:如果传数组,一定要用Array.isArray判断,不然checkPermission函数会把数组当成字符串处理,比如['add-user']会被当成字符串"add-user",结果判断错。
  • 忘了updated钩子:用户切换角色后,权限变了但按钮状态没更,就是因为没触发updated,一定要加这个钩子。
  • 没处理userPermsundefined:如果用户没登录,userPerms可能是undefined,所以要给个默认值[],不然checkPermission函数会报错。
  • 多个权限的判断逻辑:如果需要满足其中一个权限,用some而不是every——比如v-permission="['add-user', 'edit-user']",只要有一个权限就显示,就把checkPermission里的every改成some
  • 我用这个指令做了3个项目,最慢的一次封装用了20分钟,之后改权限再也没熬夜过。你要是按这些步骤试了,不管成功还是遇到问题,都欢迎回来告诉我——比如你有没有遇到传数组参数的情况?或者切换角色后状态没更新?咱们一起聊聊怎么解决!


    我之前做电商后台的时候,遇到过一个特别常见的需求——删除商品的按钮,得同时有“商品管理权限”和“删除操作权限”才能显示,单传一个权限字符串根本搞不定。这时候你就直接给指令传个数组就行,比如写v-permission="['manage-product', 'delete-product']",把需要的多个权限都塞进去,指令会自动识别这是要“同时满足”的条件。

    接下来得改一下权限判断的核心逻辑,就是utils/permission.js里的checkPermission函数。原来判断单个权限是用includes,现在处理数组的话,得用every方法——它会遍历你传的权限数组,确认每一个权限都在用户的权限列表里。比如用户的权限是['manage-product', 'delete-product', 'view-order'],那数组里的两个权限都满足,every就返回true,按钮正常显示;但如果用户只有manage-product没有delete-productevery就返回false,按钮要么隐藏要么禁用,刚好符合“必须两个权限都有”的需求。

    要是你想反过来,让按钮满足任一权限就能显示(比如“新增或编辑用户”的按钮),把every换成some就行。比如v-permission="['add-user', 'edit-user']",用户只要有其中一个权限,some就返回true,按钮就会显示——我之前做用户管理页面的时候就这么用,运营人员有edit-user权限能看到,客服有add-user权限也能看到,不用拆分成两个按钮,特省事儿。

    对了,传数组的时候得注意语法——每个权限字符串都得用单引号包着,再用方括号括起来,别写成v-permission=[add-user, edit-user](少了单引号),不然控制台会报“add-user未定义”的错。我第一次写的时候就犯过这毛病,查了十分钟才发现是引号漏了,记着别踩这坑。

    还有个实际场景你可以参考:我之前做的“导出订单”按钮,需要“订单查看权限”和“导出权限”,当时传了数组用every,客户测试的时候说只有超级管理员能看到,普通运营看不到——刚好符合需求。后来客户要加个“运营主管”角色,只需要在他的权限列表里加这两个权限,按钮就自动显示了,不用改组件里的任何代码,维护起来特轻松。


    自定义指令和v-if做权限控制有什么区别?

    v-if是直接决定按钮是否渲染到DOM,而自定义指令可以更灵活地控制按钮状态——比如没权限时保持按钮存在但禁用(加disabled属性),或添加“无权限”提示(title属性)。 自定义指令全局注册后全项目复用,不用每个组件重复写v-if判断逻辑,维护成本更低。

    用户切换角色后,按钮权限怎么自动更新?

    指令的updated钩子会在组件更新时触发(比如用户角色切换导致权限列表变化)。只需在updated钩子中重新执行权限校验逻辑,根据新的权限状态调整按钮的显示/禁用状态,就能实现自动更新,无需手动刷新页面。

    如何让按钮需要多个权限才能显示?

    只需给指令传一个权限数组(比如v-permission=”[‘add-user’, ‘edit-user’]”),并在checkPermission函数中用every方法判断“所有权限都满足”(若需满足任一权限则用some)。这样就能实现多权限的组合判断。

    没权限时,除了隐藏按钮还能做什么?

    除了用el.style.display = ‘none’隐藏,还可以禁用按钮并添加提示:比如el.disabled = true让按钮不可点击,再用el.title = ‘您没有操作权限’鼠标悬浮时显示提示。根据项目需求选择不同的处理方式,只需修改指令内的DOM操作逻辑即可。

    状态管理(如Pinia/Vuex)里的权限变化,指令能监听到吗?

    可以。只要状态管理中的权限列表是响应式的(比如Pinia的state属性),当权限变化时,组件会触发更新,指令的updated钩子会随之执行,重新校验权限并更新按钮状态。无需额外添加监听逻辑。

    原文链接:https://www.mayiym.com/46385.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码