动态路由实现权限按钮显隐需路由与组件协同:路由meta定义页面级权限标识,守卫校验后注入上下文,组件用usepermission等逻辑控制按钮显隐,并建议接口层二次校验。

动态路由实现权限按钮显隐,核心是把用户权限和路由元信息、组件逻辑打通,不是只靠路由配置就能完成的——路由定“能进哪”,按钮显隐看“能做啥”,两者要协同,但职责分明。
一、路由配置阶段:用 meta 携带页面级权限标识
在定义动态路由时,通过 meta 字段声明该页面所需的最小权限(如字符串、数组或权限码),不写死具体按钮,而是表达「访问本页需具备哪些能力」:
- 权限标识建议统一用后端返回的权限 key(如 "user:edit"、"order:export"),避免前端自定义歧义
- 一个路由可配多个权限,用数组表示逻辑「与」关系:
meta: { permissions: ['user:list', 'user:detail'] } - 不推荐在路由里直接写按钮级控制(如
showDeleteBtn: true),否则路由配置膨胀且难以复用
二、路由守卫中校验并注入权限上下文
在 router.beforeEach 中,根据当前用户权限列表比对目标路由的 meta.permissions,校验通过后,把权限结果挂载到路由实例或全局状态中:
- 校验失败时,可重定向到 403 页面,或保留页面但禁用所有操作(取决于产品策略)
- 推荐将权限判断结果存入 route.meta.hasPermission 或使用 provide/inject / Pinia store 向下透传,供子组件消费
- 避免每次渲染都重复计算权限——校验逻辑应幂等,且权限数据通常随登录/刷新一次加载,缓存即可
三、页面组件中按需控制按钮显隐
组件内不硬编码权限字符串,而是封装可复用的权限判断逻辑:
- 定义组合式函数 usePermission(),内部读取全局权限列表,提供
has('user:delete')方法 - 模板中直接使用:
<button v-if="has('user:delete')">删除</button> - 敏感操作(如提交、删除)建议双重防护:按钮显隐 + 接口层再校验权限(防前端绕过)
- 按钮灰化(disabled)和隐藏(v-if)需区分场景:无权限时隐藏更安全;有权限但暂不可用(如表单未填)才用 disabled
四、进阶:按钮级权限也可动态注入路由
若产品要求「同一页面不同角色看到不同按钮」,可在路由 resolve 阶段动态生成带按钮配置的 route record:
- 后端返回的路由数据中,除基础字段外,增加 buttons: ['edit', 'export', 'audit'] 字段
- 前端解析时,把 buttons 映射为 meta.buttons,组件内通过
v-for="btn in $route.meta.buttons"渲染,并配合has(btn)控制显隐 - 这种方式适合中后台系统,但需前后端约定按钮语义,避免前端维护两套权限体系
权限按钮的显隐本质是「能力可见性」问题,路由负责准入控制,组件负责操作粒度控制,中间靠权限上下文串联。链路清晰了,扩展和排查就简单。









