Как я могу создать пользовательский перенаправитель в Angular 10?

#angular #angular-routing

#angular #angular-маршрутизация

Вопрос:

Я использую маршрутизацию в своем проекте angular для навигации по сайту, однако я хотел бы перенаправить пользователя с URL-адреса root / host на основе различных условий, и я не уверен, что это возможно с маршрутизатором Angular.

Поэтому я попытался создать a HomeComponent для обработки этих перенаправлений.

Вот блок-схема, объясняющая, чего я пытаюсь достичь: Поток корневых URL

  • Если пользователь вошел в систему, он должен быть доставлен на соответствующий портал — тип пользователя сохраняется в токене пользователя
  • Пользователи должны иметь доступ только к порталу, которому они были назначены
  • Пользователь не должен иметь доступа к странице входа в систему, если он вошел в систему

В моем основном модуле маршрутизации приложений у меня есть это:

 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;
    }
}