Vue3组合式API:能否自定义defineComponent实现组件权限校验?
实现方案:通过自定义
defineComponent处理组件权限校验 完全可以通过封装自定义的组件定义函数来实现你的需求,既能全局仅读取一次localStorage中的权限,又能最小化现有代码的改动。以下是具体实现步骤:
1. 全局缓存用户权限集合
先创建一个工具模块,全局仅读取一次localStorage中的权限并转为Set(提升权限判断效率):
// utils/permission.js // 全局初始化时读取一次用户权限,缓存到内存中 const rawUserClaims = localStorage.getItem('userClaims'); const userClaims = rawUserClaims ? JSON.parse(rawUserClaims) : []; export const userClaimSet = new Set(userClaims); // 通用权限校验函数 export const hasClaim = (claim) => userClaimSet.has(claim);
如果后续需要更新用户权限(比如登录后),可以添加一个更新方法:
// 在utils/permission.js中追加 export const updateUserClaims = () => { const raw = localStorage.getItem('userClaims'); const newClaims = raw ? JSON.parse(raw) : []; userClaimSet.clear(); newClaims.forEach(claim => userClaimSet.add(claim)); };
2. 封装自定义权限组件定义函数
封装defineAuthComponent,它会自动处理组件配置中的claims,生成带Enabled后缀的权限状态,并注入到setup函数中:
// utils/defineAuthComponent.js import { defineComponent } from 'vue'; import { hasClaim } from './permission'; export function defineAuthComponent(options) { // 兼容未配置claims的组件,直接返回原生defineComponent结果 if (!options.claims) { return defineComponent(options); } // 解析claims配置,生成权限开关状态 const authState = Object.entries(options.claims).reduce((acc, [key, claim]) => { acc[`${key}Enabled`] = hasClaim(claim); return acc; }, {}); // 保存原setup函数,并重写注入权限状态 const originalSetup = options.setup; options.setup = (props, context) => { // 调用原setup,把权限状态作为第一个参数传入 const setupResult = originalSetup?.(authState, props, context) || {}; // 合并权限状态到返回值(避免组件setup忘记返回) return { ...authState, ...setupResult }; }; // 删除原claims配置,避免Vue处理未知选项 delete options.claims; return defineComponent(options); }
3. 组件中的实际使用
和你设想的用法几乎一致,仅需替换defineComponent为我们封装的函数:
// components/Dictionary.vue import { defineAuthComponent } from '@/utils/defineAuthComponent'; import { Claim } from '@/enums/claim'; export default defineAuthComponent({ claims: { create: Claim.DictCreate, edit: Claim.DictUpdate, delete: Claim.DictDelete }, setup(claims) { // 这里的claims就是{ createEnabled: boolean, editEnabled: boolean, deleteEnabled: boolean } return { claims }; } });
模板中直接使用权限状态控制元素显隐:
<template> <create-button v-if="claims.createEnabled" /> <edit-button v-if="claims.editEnabled" /> <delete-button v-if="claims.deleteEnabled" /> </template>
4. 额外注意事项
- 确保权限枚举
Claim的全局一致性,避免值或拼写错误导致校验失效。 - 若使用TypeScript,可以给
defineAuthComponent添加类型定义,让setup中的claims参数获得准确的类型提示。 - 该方案无需大规模重构现有组件,仅需替换组件定义函数并添加
claims配置即可。
内容的提问来源于stack exchange,提问作者Fesq
相关产品推荐
相关产品推荐

