我的 a 有一个模块,其中包含自己的子路由。本质上,该页面的唯一内容是标题和一些链接到我的路由的材料选项卡,因此我只会显示其中之一。但是,无论我在桌面上还是在移动设备上,我希望登陆选项卡有所不同。
我有一个名为 ToolService 的服务,其中包含 ToolService.isDesktopOrTablet() 方法,我通常用它来进行平台检测。
在意识到我希望redirectTo指向移动设备上的“列表”而不是“树”之前,我的路由模块看起来像这样
export const routes: Routes = [
{
path: '',
component: ExampleComponent,
children: [{
path: '',
redirectTo: 'tree',
pathMatch: 'full',
}, {
path: 'tree',
component: ExampleTreeComponent,
title: 'Example Title',
}, {
path: 'list',
component: ExampleListComponent,
title: 'Example Title',
}]
}
]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [],
})
export class ExampleRoutingModule {
}
我尝试的第一件事是使用基于类别的守卫。就在那时,我了解到 Angular 15 中基于类的守卫已被弃用,取而代之的是功能性守卫。
我尝试的第二件事是使用功能性守卫,但我收到了一条警告消息,告诉我 canActivate 和 redirectTo 不能很好地配合使用,因为重定向是在守卫之前处理的。
这让我想到了我尝试的第三个解决方案,解析器:
export const exampleResolver: ResolveFn<string> = (): string => inject(ToolService).isDesktopOrTablet() ? 'tree' : 'list'
export const routes: Routes = [
{
path: '',
component: ExampleComponent,
children: [{
path: '',
redirectTo: '',
pathMatch: 'full',
resolve: {
redirectTo: exampleResolver
},
}, {
path: 'tree',
component: ExampleTreeComponent,
title: 'Example Title',
}, {
path: 'list',
component: ExampleListComponent,
title: 'Example Title',
}]
}
]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [],
providers: [ToolService]
})
export class ExampleRoutingModule {
}
这似乎不会引发任何错误消息,但它似乎也没有执行任何操作。当我导航到主路线时,我的应用程序停留在 '' 路线上,而没有实际重定向到任何内容,就好像解析器从未执行过一样,这让我想到了我的问题:
说到重定向,它属于
guards
的范畴,所以你可以编写一个canActivateFn来根据平台类型进行重定向。代码的粗略估计如下所示!
export const platformRedirectGuard: CanActivateFn = (
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
const toolService = inject(ToolService);
const router = inject(Router);
const path = toolService.isDesktopOrTablet() ? 'tree' : 'list';
return router.navigate([path]); // you need to fine tune this, because the solution that works might need different variations, like relative to activated route, etc, but guards are the way to go!
};
路由
export const routes: Routes = [
{
path: '',
component: ExampleComponent,
children: [{
path: '',
redirectTo: '',
pathMatch: 'full',
canActivate: [platformRedirectGuard], // <- changed here!
}, {
path: 'tree',
component: ExampleTreeComponent,
title: 'Example Title',
}, {
path: 'list',
component: ExampleListComponent,
title: 'Example Title',
}]
}
]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [],
providers: [ToolService]
})
export class ExampleRoutingModule {
}
我会和
CanActivate
守卫一起去。
canActivate() {
if(isMobile) {
return this.router.createUrlTree(['list']);
} else {
return `true`
}
}