通过权限指令 v-permssion 按钮级别权限

image.png

5-1 创建指令

src/directive/permission/permission.ts

  1. import { ObjectDirective, DirectiveBinding, App } from 'vue'
  2. import { computed } from '@vue/reactivity'
  3. import store from '@/store'
  4. export interface IDirectiveOptionsWithInstall extends ObjectDirective {
  5. install?: (app: App) => void;
  6. }
  7. const checkPermission = (el: HTMLElement, binding: DirectiveBinding) => {
  8. const { value } = binding
  9. const roles = computed(() => store.getters.roleNames)
  10. if (value && Array.isArray(value)) {
  11. if (value.length > 0) {
  12. const permissionRoles = value
  13. const hasPermission = roles.value.some((role: string) => permissionRoles.includes(role))
  14. if (!hasPermission) { // 指令权限缺点 移除Dom后 无法恢复
  15. return el.parentNode?.removeChild(el)
  16. }
  17. } else {
  18. // eslint-disable-next-line
  19. throw new Error(`need roles! Like v-permission="['admin','editor']"`)
  20. }
  21. }
  22. }
  23. // export default {
  24. // mounted(el: HTMLElement, binding: DirectiveBinding) {
  25. // checkPermission(el, binding)
  26. // },
  27. // updated(el: HTMLElement, binding: DirectiveBinding) {
  28. // checkPermission(el, binding)
  29. // }
  30. // } as IDirectiveOptionsWithInstall
  31. // 默认相当于 mounted and updated
  32. const plugin = (el: HTMLElement, binding: DirectiveBinding) => {
  33. checkPermission(el, binding)
  34. }
  35. export default plugin as IDirectiveOptionsWithInstall

封装成vue plugin

  1. import { App } from 'vue'
  2. import permission from './permission'
  3. const install = (app: App): void => {
  4. app.directive('permission', permission)
  5. }
  6. export default install

入口注册指令

src/main.ts

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import store, { key } from './store'
  5. // 初始化css
  6. import 'normalize.css/normalize.css'
  7. // element-plus
  8. import installElementPlus, { Size } from './plugins/element'
  9. // 挂载到vue实例上
  10. import { ElMessageBox, ElMessage, ElNotification } from 'element-plus'
  11. // 用户验证
  12. import './permission'
  13. // 全局 css
  14. import '@/styles/index.scss'
  15. // svg icons
  16. import initSvgIcon from '@/icons/index'
  17. // 权限指令
  18. import permissionDirective from './directive/permission/index'
  19. const app = createApp(App)
  20. // 获取store里存储的size
  21. const size = store.state.app.size
  22. app
  23. .use(store, key)
  24. .use(router)
  25. .use(installElementPlus, {
  26. size
  27. })
  28. .use(permissionDirective) // 注册权限指令
  29. .use(initSvgIcon)
  30. .mount('#app')
  31. /**
  32. * 相关issue问题
  33. * Why not on the d.ts use it ?
  34. (为什么不能在shims-d.ts 中设置这个?
  35. * https://github.com/vuejs/vue-next/pull/982
  36. */
  37. // 挂载到vue实例上
  38. declare module '@vue/runtime-core' {
  39. interface ComponentCustomProperties {
  40. $message: typeof ElMessage;
  41. $notify: typeof ElNotification;
  42. $confirm: typeof ElMessageBox.confirm;
  43. $alert: typeof ElMessageBox.alert;
  44. $prompt: typeof ElMessageBox.prompt;
  45. $ELEMENT: {
  46. size: Size;
  47. };
  48. }
  49. }


测试

super_admin可见
image.png
其他用户角色 不可见
image.png
可以根据角色动态 分配操作类型crud权限列表 自己可以写下