Angular 6基于URL参数的路由配置:匹配器无法获取参数
嘿,我懂你碰到的这个问题了!你现在的核心困扰在于:Angular的UrlSegment数组只负责解析URL的路径部分(也就是?之前的内容),查询参数(像?id=form&row=12345这种)根本不会出现在UrlSegment里,这就是为什么你在匹配器里看到url.parameters是空对象的原因——它本来就不包含查询参数呀!
为什么你的原始方案行不通?
再明确一下:Angular的自定义路由匹配器(matcher)是专门用来匹配URL的路径段的,查询参数不属于路由路径的一部分,所以不会被传入matcher的url参数中。你写的匹配逻辑一直在检查路径里是否包含id=form,但实际上这些内容在查询参数里,完全不在匹配器的处理范围内。
两种可行的解决方案
方案1:用路由守卫+重定向(最符合Angular路由设计)
这种方式先匹配/worker路径,然后通过守卫检查查询参数,自动重定向到对应的组件路由,逻辑清晰且符合Angular的路由规范。
首先修改你的路由配置:
const routes: Routes = [ { path: 'worker', canActivate: [WorkerRouteGuard], // 用一个空组件占位,或者直接配置重定向逻辑 component: EmptyPlaceholderComponent }, { path: 'form', component: FormComponent }, { path: 'list', component: ListComponent }, { path: '**', component: PageComponent } ];
然后创建WorkerRouteGuard守卫类:
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class WorkerRouteGuard implements CanActivate { constructor(private router: Router) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { const idParam = route.queryParams['id']; const rowParam = route.queryParams['row']; if (idParam === 'form') { // 把row参数一起传递到form路由 this.router.navigate(['/form'], { queryParams: { row: rowParam }, queryParamsHandling: 'merge' }); return false; } else if (idParam === 'list') { this.router.navigate(['/list']); return false; } else { // 参数不合法时跳转到404页面 this.router.navigate(['/page']); return false; } } }
注:EmptyPlaceholderComponent可以是一个没有任何内容的空组件,用来作为守卫的载体。
方案2:在父组件中动态加载目标组件
如果你不想调整路由结构,可以创建一个WorkerComponent作为父容器,在里面根据查询参数动态渲染对应的组件:
先修改路由配置:
const routes: Routes = [ { path: 'worker', component: WorkerComponent }, { path: '**', component: PageComponent } ];
然后编写WorkerComponent的代码:
import { Component, OnInit, ViewContainerRef, ComponentFactoryResolver } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { FormComponent } from './form/form.component'; import { ListComponent } from './list/list.component'; import { PageComponent } from './page/page.component'; @Component({ template: `<ng-container #componentHost></ng-container>` }) export class WorkerComponent implements OnInit { constructor( private route: ActivatedRoute, private componentFactoryResolver: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef ) {} ngOnInit(): void { // 监听查询参数变化,动态切换组件 this.route.queryParams.subscribe(params => { const id = params['id']; this.loadTargetComponent(id); }); } private loadTargetComponent(id: string): void { this.viewContainerRef.clear(); let targetComponent: any; switch(id) { case 'form': targetComponent = FormComponent; break; case 'list': targetComponent = ListComponent; break; default: targetComponent = PageComponent; break; } const componentFactory = this.componentFactoryResolver.resolveComponentFactory(targetComponent); this.viewContainerRef.createComponent(componentFactory); } }
这样当用户访问/worker?id=form&row=12345时,WorkerComponent会自动加载FormComponent;访问/worker?id=list时加载ListComponent,完全符合你的预期。
内容的提问来源于stack exchange,提问作者SimonMorris

