vue+typescript解决无法使用路由组件内守卫

本文探讨了在Vue+TypeScript环境下遇到的组件内无法调用路由钩子如beforeRouteEnter的问题。通过引入registerHooks.js来注册组件钩子,解决了在组件实例化前无法访问this的难题。同时展示了两种使用beforeRouteEnter的方法,确保了在正确的时间点执行守卫逻辑。

vue + typescript 开发环境
组件内无法调用路由钩子:beforeRouterEnter等守卫
需要向Component注册hooks

import { Vue, Component } from "vue-property-decorator";
import { Divider } from "ant-design-vue";
import { RouteConfig } from "vue-router";
import { getUserList } from "@/api/user/user";
//registerHooks.js
// 可以将注册钩子的代码,抽取公共代码
Component.registerHooks([
  "beforeRouteEnter",
  "beforeRouteLeave",
  "beforeRouteUpdate"
]);

@Component({
  components: {
    ADivider: Divider,
  },
  // 用法2
  // beforeRouteEnter(to, from, next) {
  //   console.log("组件内守卫");
  //   console.log(this); // 进入组件之前未被实例化,无法访问this
  // }
})
export default class NAME extends Vue {
  // 用法1
  // typescript 暂时不熟练,写法可能不是最优。
  beforeRouteEnter(to: RouteConfig, from: RouteConfig, next: Function): void {
    console.log("组件内守卫");
    console.log(this); // 进入组件之前未被实例化,无法直接访问this
    next((vm: object) => {
      console.log(vm);
    });
  }
}
<think>嗯,用户现在想实现基于Vue3、TypeScriptVuex的路由菜单和按钮权限管理。首先,我需要回顾一下之前关于Vuex的讨论,之前已经给出了Vue3和TypeScript配置Vuex的示例,包括模块化结构和类型定义。现在用户的需求涉及到路由和权限管理,可能需要结合动态路由和状态管理。 首先,用户提到了路由菜单和按钮权限。这通常涉及到根据用户权限动态生成可访问的路由,并控制页面中的按钮显示。根据引用[4]中的内容,Vue3可以使用router.addRoute()动态添加路由,这可能需要在登录后根据权限数据动态加载路由。同时,按钮权限可能需要一个全局指令来控制是否显示。 接下来,用户需要使用Vuex来管理权限状态。之前的回答中提到了模块化的Vuex结构,所以可能需要创建一个权限模块(permissionModule),存储路由权限和按钮权限的数据。需要定义state、mutations、actions来处理权限数据的获取和更新。 然后,考虑如何将动态路由Vuex结合。用户登录后,可能需要从后端获取权限数据,然后提交到Vuex的action,处理生成可访问的路由,并调用router.addRoute()动态添加。同时,菜单组件需要从Vuex中获取生成的路由数据来渲染菜单。 对于按钮权限,可以创建一个自定义指令v-permission,根据Vuex中的按钮权限数据控制元素的显示隐藏。这需要指令内部访问Vuex的状态,并在权限变更时更新。 另外,类型定义也是关键。需要为权限模块定义TypeScript接口,如PermissionState,包含routes和buttons等字段,确保类型安全。同时,在动态生成路由时,可能需要处理路由配置的类型,确保符合Vue Router的要求。 还需要考虑持久化的问题,比如用户刷新后如何重新获取权限数据。可能需要结合本地存储,或者在应用初始化时检查用户登录状态并重新获取权限。 用户可能的问题包括如何组织权限模块的结构,如何动态添加路由,如何实现按钮指令,以及如何处理类型定义。需要确保示例代码清晰展示这些部分,并引用之前的相关内容,比如模块化Vuex和类型增强。 最后,生成相关问题时要围绕权限管理的扩展,比如如何优化、如何处理动态路由的移除、与Pinia的区别等,帮助用户深入理解。</think>### Vue3 + TypeScript + Vuex 实现路由菜单与按钮权限管理方案 #### 一、核心架构设计 ```typescript // store/modules/permission.ts interface RouteMeta { title: string requiresAuth?: boolean permissions?: string[] } export interface PermissionState { dynamicRoutes: RouteRecordRaw[] // 动态生成的路由表 buttonPermissions: string[] // 当前用户按钮权限集合 } ``` #### 二、Vuex 权限模块实现 ```typescript const permissionModule: Module<PermissionState, RootState> = { namespaced: true, state: (): PermissionState => ({ dynamicRoutes: [], buttonPermissions: [] }), mutations: { SET_ROUTES(state, routes) { state.dynamicRoutes = routes }, SET_BUTTON_PERMISSIONS(state, permissions) { state.buttonPermissions = permissions } }, actions: { async generateRoutes({ commit }, role: string) { // 根据角色获取路由配置 const accessedRoutes = await fetchRoutesByRole(role) // 动态添加路由 accessedRoutes.forEach(route => { router.addRoute(route) }) commit('SET_ROUTES', accessedRoutes) } } } ``` #### 三、路由守卫集成方案 ```typescript // router/index.ts router.beforeEach(async (to, from, next) => { const store = useStore() if (to.meta.requiresAuth) { // 权限验证逻辑 if (!store.getters['user/isLoggedIn']) { next('/login') } else { // 首次加载时生成动态路由 if (store.state.permission.dynamicRoutes.length === 0) { await store.dispatch('permission/generateRoutes', store.state.user.role) next({ ...to, replace: true }) } else { next() } } } else { next() } }) ``` #### 四、按钮权限指令实现 ```typescript // directives/permission.ts const permissionDirective = { mounted(el: HTMLElement, binding: DirectiveBinding) { const store = useStore() const hasPermission = store.state.permission.buttonPermissions.includes(binding.value) if (!hasPermission) { el.parentNode?.removeChild(el) } } } // main.ts app.directive('permission', permissionDirective) ``` #### 五、动态菜单组件示例 ```vue <!-- components/SidebarMenu.vue --> <template> <el-menu> <template v-for="route in accessedRoutes"> <sub-menu :item="route" :key="route.path" /> </template> </el-menu> </template> <script setup lang="ts"> import { computed } from 'vue' import { useStore } from 'vuex' const store = useStore() const accessedRoutes = computed(() => store.state.permission.dynamicRoutes) </script> ``` #### 六、权限数据持久化方案 ```typescript // 用户登录成功后存储权限信息 const handleLogin = async () => { await store.dispatch('user/login', credentials) await store.dispatch('permission/generateRoutes', user.role) localStorage.setItem('BUTTON_PERMISSIONS', JSON.stringify(store.state.permission.buttonPermissions)) } // 应用初始化时恢复权限 const initPermission = () => { const savedPermissions = localStorage.getItem('BUTTON_PERMISSIONS') if (savedPermissions) { store.commit('permission/SET_BUTTON_PERMISSIONS', JSON.parse(savedPermissions)) } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小于___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值