У меня есть модуль 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 {
}
Кажется, это не вызывает никаких сообщений об ошибках, но, похоже, ничего не делает. Когда я перехожу к основному маршруту, мое приложение остается на маршруте, фактически не перенаправляясь ни на что, как если бы преобразователь никогда не выполнялся, что приводит меня к моим вопросам:
Я бы выбрал охрану CanActivateFn.
function canActivate() {
const router = inject(Router)
if (isMobile) {
return router.createUrlTree(['list']);
} else {
return true
}
}
Логическое значение, конечно! (как часть подписи CanActivate
)
Когда я пытался это сделать, я получил предупреждение о том, что canActivate
и redirectTo
не работают вместе, поскольку перенаправления обрабатываются раньше защиты. Разве это не беспокойство?
Я бы использовал охрану на пути 'tree'
. Делаем ''
простым перенаправлением на 'tree'
.
Это звучит многообещающе. Является ли createUrlTree
таким, чтобы в случае сбоя защиты он перенаправлялся на список?
точно, canActivate принимает UrlTree
в качестве возвращаемого значения и перенаправляет на него.
Нужно ли мне использовать фабрику? Константа маршрутов объявлена вне моего модуля, поэтому this.router
не определена, не так ли? Или вы предлагаете мне перенести это из моего модуля в мой компонент?
ты можешь использовать inject(Router)
На самом деле еще один вопрос: нужно ли мне включать Router (и, в моем случае, ToolService) в поставщики модулей, когда я это делаю?
В этом нет необходимости, этим занимается корневой инжектор.
Вернуть строку
true
?