路由基础 #
一、路由概述 #
Angular路由允许在单页面应用中实现多视图导航,通过URL变化切换不同的组件视图。
text
┌─────────────────────────────────────────────────────┐
│ Angular 应用 │
├─────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────┐ │
│ │ Router Outlet │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ 根据URL显示对应组件 │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────┐ │
│ │ /home → HomeComponent │ │
│ │ /users → UsersComponent │ │
│ │ /users/:id → UserDetailComponent │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
二、路由配置 #
2.1 创建路由配置 #
typescript
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { UsersComponent } from './users/users.component';
import { UserDetailComponent } from './user-detail/user-detail.component';
export const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', component: UsersComponent },
{ path: 'users/:id', component: UserDetailComponent },
{ path: '**', redirectTo: '' }
];
2.2 注册路由 #
app.routes.ts:
typescript
import { Routes } from '@angular/router';
export const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];
app.config.ts:
typescript
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes)
]
};
2.3 路由出口 #
html
<!-- app.component.html -->
<nav>
<a routerLink="/">首页</a>
<a routerLink="/users">用户</a>
<a routerLink="/about">关于</a>
</nav>
<router-outlet></router-outlet>
三、路由导航 #
3.1 routerLink指令 #
html
<!-- 基本导航 -->
<a routerLink="/home">首页</a>
<a routerLink="/users">用户列表</a>
<!-- 相对路径 -->
<a routerLink="./detail">详情</a>
<a routerLink="../list">返回列表</a>
<!-- 数组语法(推荐) -->
<a [routerLink]="['/users', userId]">用户详情</a>
<a [routerLink]="['/products', productId, 'edit']">编辑产品</a>
3.2 routerLinkActive #
html
<!-- 高亮当前路由 -->
<a routerLink="/home" routerLinkActive="active">首页</a>
<a routerLink="/users" routerLinkActive="active">用户</a>
<!-- 多个类名 -->
<a routerLink="/home" [routerLinkActive]="['active', 'highlighted']">首页</a>
<!-- 配置选项 -->
<a
routerLink="/home"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }">
首页
</a>
3.3 编程式导航 #
typescript
import { Router } from '@angular/router';
@Component({
template: `
<button (click)="goToUsers()">前往用户列表</button>
<button (click)="goToUserDetail(1)">查看用户详情</button>
`
})
export class ExampleComponent {
constructor(private router: Router) {}
goToUsers() {
this.router.navigate(['/users']);
}
goToUserDetail(id: number) {
this.router.navigate(['/users', id]);
}
goBack() {
this.router.navigate(['..']);
}
}
3.4 带查询参数导航 #
typescript
// 导航带查询参数
this.router.navigate(['/users'], {
queryParams: { page: 1, size: 10 }
});
// URL: /users?page=1&size=10
// 导航带片段
this.router.navigate(['/users'], {
fragment: 'section-1'
});
// URL: /users#section-1
// 完整示例
this.router.navigate(['/users', userId], {
queryParams: { tab: 'profile' },
fragment: 'comments'
});
// URL: /users/123?tab=profile#comments
四、路由参数 #
4.1 路径参数 #
路由配置:
typescript
const routes: Routes = [
{ path: 'users/:id', component: UserDetailComponent },
{ path: 'products/:category/:id', component: ProductDetailComponent }
];
获取参数:
typescript
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-user-detail',
template: '<p>用户ID: {{ userId }}</p>'
})
export class UserDetailComponent implements OnInit {
userId: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 方式1:快照获取(一次性)
this.userId = this.route.snapshot.paramMap.get('id');
// 方式2:订阅获取(参数变化时更新)
this.route.paramMap.subscribe(params => {
this.userId = params.get('id');
});
}
}
4.2 查询参数 #
typescript
import { ActivatedRoute } from '@angular/router';
@Component({
template: '<p>页码: {{ page }}</p>'
})
export class UsersComponent implements OnInit {
page: number;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 快照获取
this.page = +this.route.snapshot.queryParamMap.get('page');
// 订阅获取
this.route.queryParamMap.subscribe(params => {
this.page = +params.get('page') || 1;
});
}
}
4.3 获取所有参数 #
typescript
@Component({
template: '...'
})
export class DetailComponent implements OnInit {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 路径参数
this.route.params.subscribe(params => {
console.log('路径参数:', params);
});
// 查询参数
this.route.queryParams.subscribe(params => {
console.log('查询参数:', params);
});
// 所有参数
this.route.paramMap.subscribe(paramMap => {
console.log('ID:', paramMap.get('id'));
});
this.route.queryParamMap.subscribe(queryParamMap => {
console.log('Page:', queryParamMap.get('page'));
});
}
}
五、嵌套路由 #
5.1 配置嵌套路由 #
typescript
const routes: Routes = [
{
path: 'users',
component: UsersComponent,
children: [
{ path: '', component: UserListComponent },
{ path: ':id', component: UserDetailComponent },
{ path: ':id/edit', component: UserEditComponent }
]
}
];
5.2 父组件模板 #
typescript
@Component({
selector: 'app-users',
template: `
<h2>用户管理</h2>
<nav>
<a routerLink="./">用户列表</a>
<a routerLink="./1">用户详情</a>
</nav>
<router-outlet></router-outlet>
`
})
export class UsersComponent {}
5.3 多级嵌套 #
typescript
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
{
path: 'users',
component: AdminUsersComponent,
children: [
{ path: '', component: UserListComponent },
{ path: ':id', component: UserDetailComponent }
]
},
{
path: 'products',
component: AdminProductsComponent
}
]
}
];
六、路由懒加载 #
6.1 配置懒加载 #
typescript
const routes: Routes = [
{ path: '', component: HomeComponent },
{
path: 'admin',
loadChildren: () => import('./admin/admin.module')
.then(m => m.AdminModule)
},
{
path: 'users',
loadComponent: () => import('./users/users.component')
.then(c => c.UsersComponent)
}
];
6.2 懒加载模块 #
admin/admin.module.ts:
typescript
@NgModule({
imports: [
RouterModule.forChild([
{ path: '', component: AdminDashboardComponent },
{ path: 'settings', component: AdminSettingsComponent }
])
],
declarations: [
AdminDashboardComponent,
AdminSettingsComponent
]
})
export class AdminModule {}
6.3 预加载策略 #
typescript
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';
export class CustomPreloadingStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data?.preload) {
return load();
}
return of(null);
}
}
// 配置
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes, withPreloading(PreloadAllModules))
]
};
七、路由事件 #
7.1 监听路由事件 #
typescript
import { Component } from '@angular/core';
import { Router, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
@Component({
selector: 'app-root',
template: '...'
})
export class AppComponent {
constructor(private router: Router) {
this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
console.log('导航开始:', event.url);
}
if (event instanceof NavigationEnd) {
console.log('导航结束:', event.url);
}
if (event instanceof NavigationError) {
console.error('导航错误:', event.error);
}
});
}
}
7.2 常用路由事件 #
| 事件 | 说明 |
|---|---|
NavigationStart |
导航开始 |
NavigationEnd |
导航结束 |
NavigationCancel |
导航取消 |
NavigationError |
导航错误 |
RoutesRecognized |
路由识别 |
GuardsCheckStart |
守卫检查开始 |
GuardsCheckEnd |
守卫检查结束 |
八、路由数据 #
8.1 静态数据 #
typescript
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
data: {
title: '管理后台',
breadcrumb: '管理',
requiresAuth: true
}
}
];
typescript
@Component({
template: '<h1>{{ title }}</h1>'
})
export class AdminComponent implements OnInit {
title: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.data.subscribe(data => {
this.title = data['title'];
});
}
}
8.2 动态数据(Resolve) #
typescript
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class UserResolver implements Resolve<User> {
constructor(private userService: UserService) {}
resolve(route: ActivatedRouteSnapshot): Observable<User> {
const id = route.paramMap.get('id');
return this.userService.getUser(+id);
}
}
// 路由配置
const routes: Routes = [
{
path: 'users/:id',
component: UserDetailComponent,
resolve: {
user: UserResolver
}
}
];
// 组件中使用
@Component({
template: '<p>{{ user?.name }}</p>'
})
export class UserDetailComponent implements OnInit {
user: User;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.data.subscribe(data => {
this.user = data['user'];
});
}
}
九、总结 #
| 概念 | 说明 |
|---|---|
Routes |
路由配置数组 |
router-outlet |
路由出口 |
routerLink |
声明式导航 |
Router.navigate() |
编程式导航 |
ActivatedRoute |
当前路由信息 |
| 懒加载 | 按需加载模块 |
| Resolve | 路由前获取数据 |
下一步:路由守卫
最后更新:2026-03-26