如何在Angular 2/5中从RouterLinkWithHref获取匹配路由?
解决Angular指令中通过RouterLinkWithHref获取路由配置data的问题
我来帮你搞定这个需求!你已经用@ContentChild拿到了RouterLinkWithHref,接下来只需要借助Angular Router的内置方法,就能匹配到对应的路由配置并读取data里的权限信息。下面是具体实现步骤和思路:
一、修改指令实现路由匹配
首先要在指令中注入Router服务,它提供了路由匹配的核心方法。我们可以通过RouterLinkWithHref的urlTree属性,去匹配路由配置中对应的Route对象:
import { Directive, ContentChild, AfterViewInit, ElementRef } from '@angular/core'; import { RouterLinkWithHref, Router, RoutesRecognized } from '@angular/router'; @Directive({ selector: '[roleCheck]' }) export class RoleCheckDirective implements AfterViewInit { @ContentChild(RouterLinkWithHref) routerLinkWithHref: RouterLinkWithHref; constructor( private elementRef: ElementRef<HTMLElement>, private router: Router ) { } ngAfterViewInit() { // 先判断是否拿到了RouterLinkWithHref实例 if (!this.routerLinkWithHref) return; // 获取RouterLink对应的UrlTree(路由的结构化表示) const urlTree = this.routerLinkWithHref.urlTree; // 用Router的match方法匹配路由配置,得到匹配到的路由数组 const matchedRoutes = this.router.routerState.snapshot.match(urlTree); // 找到包含roles配置的路由项(通常取数组最后一项,因为嵌套路由会匹配多个层级) const targetRoute = matchedRoutes.find(route => route.routeConfig?.data?.roles); if (targetRoute?.routeConfig?.data?.roles) { const requiredRoles = targetRoute.routeConfig.data.roles; // 替换成你的实际权限校验逻辑:比如当前用户角色是否在requiredRoles中 const hasPermission = this.checkUserPermission(requiredRoles); if (!hasPermission) { // 隐藏或移除菜单项,这里用display:none示例,也可以用remove()直接删除元素 this.elementRef.nativeElement.style.display = 'none'; } } } // 示例权限校验方法,根据你的实际业务修改 private checkUserPermission(requiredRoles: string[]): boolean { // 假设你有一个Auth服务存储当前用户角色 // const currentRoles = this.authService.getUserRoles(); // return requiredRoles.some(role => currentRoles.includes(role)); return false; // 这里替换成真实的校验逻辑 } }
二、处理懒加载路由的情况
如果你的路由是懒加载的,ngAfterViewInit执行时懒加载的路由配置可能还没加载完成,导致匹配失败。这时候可以监听Router的RoutesRecognized事件,在路由加载完成后再执行匹配逻辑:
ngAfterViewInit() { this.router.events.subscribe(event => { // 只在路由识别完成后执行匹配 if (event instanceof RoutesRecognized && this.routerLinkWithHref) { const urlTree = this.routerLinkWithHref.urlTree; const matchedRoutes = this.router.routerState.snapshot.match(urlTree); // 后续的权限校验和元素隐藏逻辑同上 } }); }
三、RouterLinkActive的实现思路
你提到RouterLinkActive能识别路由并高亮,它的核心逻辑其实和我们上面的实现类似:
- 监听路由变化事件
- 调用
Router.isActive()方法,判断当前路由是否和RouterLink的urlTree匹配 - 根据匹配结果添加/移除激活类
你可以查看它的源码来了解细节:在本地项目的node_modules/@angular/router/src/directives/router_link_active.ts文件中,核心代码是通过this.router.isActive(this.routerLink.urlTree, this.options.exact)来判断激活状态的,而isActive底层也是基于路由匹配逻辑实现的。
四、查看Angular Router源码的途径
- IDE跳转定义:在VS Code中,右键点击
RouterLinkActive、Router等类,选择「转到定义」,可以直接查看类型定义和源码(如果你的node_modules中包含了Angular的源码文件,默认可能只有.d.ts类型定义,你可以通过安装源码包或者直接查看GitHub上的Angular仓库) - 本地node_modules:直接打开
node_modules/@angular/router/src目录,里面包含了所有Router模块的源码文件,比如router.ts(路由核心逻辑)、router_link_with_href.ts(RouterLinkWithHref的实现)等
内容的提问来源于stack exchange,提问作者Irshad Ali
相关产品推荐
相关产品推荐

