Angular学习之路由「Routing」

1. 路由概述

在前端应用中,路由是一个非常重要的概念。路由的作用是将不同的 URL 映射到不同的页面或组件上,让用户可以方便地在不同的页面之间切换。在 Angular 中,我们可以使用内置的路由模块来实现这个功能。

1.1 路由的基本用法

在 Angular 中,我们可以通过在 app.module.ts 文件中引入 RouterModule 模块来使用路由功能。RouterModule 模块提供了两个方法:forRoot 和 forChild,其中 forRoot 方法主要用于在根模块中配置路由规则,而 forChild 方法则用于在子模块中配置路由规则。

import { NgModule } from '@angular/core';

import { Routes, RouterModule } from '@angular/router';

import { HomeComponent } from './home.component';

import { AboutComponent } from './about.component';

const routes: Routes = [

{ path: '', component: HomeComponent },

{ path: 'about', component: AboutComponent }

];

@NgModule({

imports: [RouterModule.forRoot(routes)],

exports: [RouterModule]

})

export class AppRoutingModule { }

上面的代码展示了一个简单的路由配置。我们定义了两个路由规则,一个是根路由,一个是 about 路由。其中根路由使用了空字符串作为路径,它会默认导航到 HomeComponent 组件;而 about 路由的路径是 'about',它会导航到 AboutComponent 组件。

1.2 路由参数传递

在实际开发中,我们经常需要在路由之间传递参数。比如,在一个电商网站中,我们可能需要在商品列表页和商品详情页之间传递一个商品的 ID,以便在详情页中显示对应的商品信息。

在 Angular 中,我们可以使用路由参数来实现这个功能。我们可以在路由模块中的路由规则中定义参数,然后通过 ActivatedRoute 服务来获取这些参数。

import { NgModule } from '@angular/core';

import { Routes, RouterModule } from '@angular/router';

import { HomeComponent } from './home.component';

import { AboutComponent } from './about.component';

import { ProductComponent } from './product.component';

const routes: Routes = [

{ path: '', component: HomeComponent },

{ path: 'about', component: AboutComponent },

{ path: 'product/:id', component: ProductComponent }

];

@NgModule({

imports: [RouterModule.forRoot(routes)],

exports: [RouterModule]

})

export class AppRoutingModule { }

上面的代码展示了一个带参数的路由配置。我们在路由规则中使用了 :id 表示这是一个参数化的路由,它可以匹配任何一个形如 'product/xxx' 的 URL。我们可以在 ProductComponent 中通过 ActivatedRoute 服务来获取这个参数:

import { Component, OnInit } from '@angular/core';

import { ActivatedRoute } from '@angular/router';

@Component({

selector: 'app-product',

template: `

Product Details -- {{ productId }}

`

})

export class ProductComponent implements OnInit {

productId: number;

constructor(private route: ActivatedRoute) {}

ngOnInit() {

this.route.paramMap.subscribe(params => {

this.productId = +params.get('id');

});

}

}

上面的代码展示了如何在 ProductComponent 中获取路由参数。我们使用 ActivatedRoute 服务的 paramMap 属性来获取参数列表,然后使用 get 方法来获取具体的参数值。需要注意的是,参数的值默认都是字符串类型,如果我们需要将它转成数字类型,需要使用 + 进行类型转换。

2. 路由的高级用法

2.1 路由守卫

在实际开发中,我们可能需要对某些路由进行权限校验,或者根据当前用户的登录状态来判断是否可以访问某个页面。这时我们可以使用路由守卫来实现这个功能。

Angular 中提供了四种路由守卫 CanActivate, CanActivateChild, CanDeactivate 和 Resolve,我们可以通过实现这些守卫来实现不同的功能。

比如,我们现在需要对 /product 路由进行权限校验,只允许已登录的用户访问。我们可以在路由模块中对这个路由进行配置,并添加 CanActivate 守卫:

import { NgModule } from '@angular/core';

import { Routes, RouterModule } from '@angular/router';

import { ProductComponent } from './product.component';

import { LoginComponent } from './login.component';

import { AuthGuard } from './auth.guard';

const routes: Routes = [

{ path: '', redirectTo: 'product', pathMatch: 'full' },

{ path: 'product', component: ProductComponent, canActivate: [AuthGuard] },

{ path: 'login', component: LoginComponent }

];

@NgModule({

imports: [RouterModule.forRoot(routes)],

exports: [RouterModule]

})

export class AppRoutingModule { }

上面的代码展示了如何在路由模块中使用 CanActivate 守卫。我们声明了一个 AuthGuard,它实现了 CanActivate 接口,用于判断用户是否已登录。然后在路由规则中使用 canActivate 属性来指定该守卫。

AuthGuard 的具体实现如下:

import { Injectable } from '@angular/core';

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';

import { Observable } from 'rxjs';

import { AuthService } from './auth.service';

@Injectable({

providedIn: 'root'

})

export class AuthGuard implements CanActivate {

constructor(private authService: AuthService) {}

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean {

return this.authService.isLoggedIn();

}

}

AuthGuard 类中实现了 CanActivate 接口,并且在 canActivate 方法中检查当前用户是否已登录。如果已登录,返回 true,允许访问;否则跳转到登录页面。

2.2 路由拦截器

除了路由守卫,我们还可以使用路由拦截器来对路由进行拦截和处理。路由拦截器可以拦截路由的请求,并对其进行处理。比如,我们可以在路由拦截器中添加一些公共的操作,并在任何路由变化前都执行这些操作。

在 Angular 中,路由拦截器一般使用 HttpClient 拦截器来实现。HttpClient 拦截器是一个 Angular 提供的功能强大的拦截器机制,它可以在发送请求或响应时对其进行拦截和处理,可以方便地实现身份认证、错误处理、缓存等功能。

下面是一个使用 HttpClient 拦截器来实现路由拦截器的示例:

import { Injectable } from '@angular/core';

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';

import { Observable } from 'rxjs';

@Injectable()

export class JwtInterceptor implements HttpInterceptor {

intercept(request: HttpRequest, next: HttpHandler): Observable> {

// add authorization header with jwt token if available

const currentUser = JSON.parse(localStorage.getItem('currentUser'));

if (currentUser && currentUser.token) {

request = request.clone({

setHeaders: {

Authorization: `Bearer ${currentUser.token}`

}

});

}

return next.handle(request);

}

}

上面的代码展示了如何实现一个基于 JWT 的身份认证拦截器。我们在 HttpClient 拦截器中获取当前用户的 token,并将其添加到请求头中。这样,在任何请求发出之前都会经过这个拦截器,从而实现了路由拦截的目的。