#angular #angular-routing
#angular #angular-маршрутизация
Вопрос:
Я использую маршрутизацию в своем проекте angular для навигации по сайту, однако я хотел бы перенаправить пользователя с URL-адреса root / host на основе различных условий, и я не уверен, что это возможно с маршрутизатором Angular.
Поэтому я попытался создать a HomeComponent
для обработки этих перенаправлений.
Вот блок-схема, объясняющая, чего я пытаюсь достичь:
- Если пользователь вошел в систему, он должен быть доставлен на соответствующий портал — тип пользователя сохраняется в токене пользователя
- Пользователи должны иметь доступ только к порталу, которому они были назначены
- Пользователь не должен иметь доступа к странице входа в систему, если он вошел в систему
В моем основном модуле маршрутизации приложений у меня есть это:
import { HomeComponent } from './../home/home.component';
import { LoginComponent } from './../login/login.component';
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
const appRoutes: Routes = [
{
path: 'login',
component: LoginComponent
},
{
path: 'staff',
loadChildren: () => import('../staff-portal/staff-portal.module').then(m => m.StaffPortalModule)
},
{
path: '**',
component: HomeComponent
},
];
@NgModule({
imports: [
CommonModule,
RouterModule.forRoot(
appRoutes,
{
preloadingStrategy: PreloadAllModules
}
)
],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Мой домашний (перенаправляющий) компонент:
import { AuthService } from './../_services/auth.service';
import { NavigationStart, Router } from '@angular/router';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
template: ''
})
export class HomeComponent {
constructor(private authService: AuthService, private router: Router) {
if (this.authService.loggedIn)
{
let parsedToken = this.authService.getParsedToken();
if (parsedToken.type === '0')
{
this.router.navigate(['/staff/home']);
return;
}
else if (parsedToken.type === '1')
{
this.router.navigate(['/student/home']);
return;
}
else if (parsedToken.type === '2')
{
this.router.navigate(['/parent/home']);
return;
}
}
this.router.navigate(['/login']);
return;
}
}
Проблема, с которой я сталкиваюсь на данный момент, заключается в том, что, когда пользователь не входит в систему и переходит к корню, angular пытается отобразить HomeComponent
шаблон (пустую строку).
Я не совсем уверен, что использование компонента является правильным способом реализации такого поведения, это как раз то, что мне удалось придумать до сих пор, но, пожалуйста, не стесняйтесь предлагать альтернативу.
Ответ №1:
Я бы посоветовал изучить Route guards для решения логики маршрутизации в зависимости от статуса аутентификации.
Таким образом, вместо того, чтобы писать свою логику перенаправления внутри компонента, вы можете вместо этого сохранить ее красивой и аккуратной внутри класса guard.
Пример конфигурации маршрута:
{
path: '/your-path',
component: YourComponent,
canActivate: [YourGuard],
}
Пример защитного кода:
export class YourGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
// your logic goes here
}
}
Ответ №2:
Используйте AuthGuard с canLoad:
//routes
{
path: 'staff',
loadChildren: () => import('../staff-portal/staff-portal.module').then(m => m.StaffPortalModule),
canLoad: [AuthGuard]
},
//auth-guard.service.ts
import { Router, CanLoad, Route } from '@angular/router';
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanLoad {
constructor(
private authService: AuthService,
private router: Router
) {}
canLoad(route: Route): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.router.navigate(['', 'login']);
return false;
}
}
//auth.service.ts
import { LocalStorageService } from './local-storage.service';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
@Injectable()
export class AuthService {
constructor(
private localStorageService: LocalStorageService,
private router: Router
) {}
login(data) {
this.localStorageService.set('token', data.token);
this.router.navigate(['', 'staff']);
}
logout() {
window.localStorage.clear();
this.router.navigate(['']);
}
isLoggedIn(): boolean {
if (this.localStorageService.get('token')) {
return true;
}
return false;
}
}