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,并将其添加到请求头中。这样,在任何请求发出之前都会经过这个拦截器,从而实现了路由拦截的目的。