Angular Router
Angular 框架内置的企业级路由系统,提供完整的导航控制、路由守卫、懒加载、预加载策略和路由动画能力,是 Angular 应用唯一的路由方案。
Angular Router 是 Angular 框架内置的企业级路由系统,提供五层路由守卫、智能预加载策略、View Transitions API 集成和完整的 RxJS 导航事件流,随 Angular CLI 自动包含。
Angular Router
Angular 框架内置的企业级路由系统,提供完整的导航控制、路由守卫、懒加载、预加载策略和路由动画能力,是 Angular 应用唯一的路由方案。
技术简介说明
Angular Router(@angular/router)是 Angular 框架的核心内置库,由 Google Angular 团队开发和维护。与 React/Vue 生态中的独立路由库不同,Angular Router 与框架深度集成——它在 Angular CLI 创建项目时自动包含,无需额外安装。Router 提供了从基础路由配置到企业级路由管理的完整能力:组件路由、模块/组件懒加载、多层路由守卫、数据预取(Resolve)、预加载策略、路由切换动画、滚动恢复等。
Angular Router 的设计哲学围绕企业级复杂需求展开。它通过 Routes 配置树定义路由结构,支持 Eager Loading(立即加载)和 Lazy Loading(按需加载)两种模式;通过五种路由守卫(canActivate、canActivateChild、canDeactivate、canMatch、resolve)实现精细的访问控制和数据预取;通过 PreloadingStrategy 实现智能预加载优化用户体验。从 v15 引入 Standalone Components 和函数式守卫开始,Angular Router 的配置模式发生了根本性变化——从 NgModule 驱动转向 provideRouter() 函数式配置。
Angular v17 是框架"文艺复兴"版本,带来了 View Transitions API 原生支持、Signals 集成、@defer 延迟视图等重大改进。v19/v20 进一步引入异步重定向、Router.getCurrentNavigation()?.abort() 导航取消 API、currentNavigation Signal(v20.2)等现代化特性。v21/v22 则聚焦于稳定性和 Zoneless 兼容。Angular Router 始终保持每 6 个月一次大版本更新的节奏,是前端路由领域最成熟的企业级方案之一。
基本信息
- 官网:https://angular.dev/guide/routing
- GitHub:https://github.com/angular/angular(monorepo 中,
packages/router/) - License:MIT
- 最新版本:Angular 22.x / @angular/router 22.0.5(2026年6月)
- 主要维护者/公司:Google / Angular 团队
- npm 周下载量:约 350 万+(2026年7月)
- GitHub Stars(Angular 整体仓库):约 98k+
快速上手
安装
# 使用 Angular CLI 创建项目(自动包含 Router)
ng new my-app --routing
# 为已有项目添加路由能力(通常已内置,无需额外操作)
ng add @angular/router
# Angular Router 是 Angular 的核心包,随 @angular/core 一起安装
# 不需要单独 npm install,只需在配置中引入 provideRouter基础配置
现代 Standalone 方式(Angular v17+,推荐):
// app.routes.ts — 路由配置
import { Routes } from '@angular/router'
export const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
{
path: 'home',
loadComponent: () =>
import('./home/home.component').then(m => m.HomeComponent),
},
{
path: 'about',
loadComponent: () =>
import('./about/about.component').then(m => m.AboutComponent),
},
{
path: 'users/:id',
loadComponent: () =>
import('./user/user-detail.component').then(m => m.UserDetailComponent),
resolve: { user: userResolver },
},
{
path: '**',
loadComponent: () =>
import('./not-found/not-found.component').then(m => m.NotFoundComponent),
},
]// app.config.ts — 应用配置
import { ApplicationConfig } from '@angular/core'
import {
provideRouter,
withPreloading,
withComponentInputBinding,
withViewTransitions,
PreloadAllModules,
} from '@angular/router'
import { routes } from './app.routes'
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(
routes,
withPreloading(PreloadAllModules),
withComponentInputBinding(),
withViewTransitions(),
),
],
}// app.component.ts — 根组件
import { Component } from '@angular/core'
import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router'
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, RouterLink, RouterLinkActive],
template: `
<nav>
<a routerLink="/home" routerLinkActive="active">首页</a>
<a routerLink="/about" routerLinkActive="active">关于</a>
</nav>
<router-outlet />
`,
})
export class AppComponent {}最小示例
// main.ts — 应用启动
import { bootstrapApplication } from '@angular/platform-browser'
import { provideRouter } from '@angular/router'
import { AppComponent } from './app.component'
import { routes } from './app.routes'
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)],
})核心概念与架构
路由配置对象(Routes)
Angular Router 使用 Routes 类型(Route[])定义路由配置树。每个 Route 对象可包含:
| 字段 | 说明 |
|---|---|
path | URL 路径段(支持参数 :id、通配符 **) |
pathMatch | 匹配策略:'prefix'(默认)或 'full'(精确匹配) |
component | 即时加载的组件(Eager Loading) |
loadComponent | 动态导入函数,返回组件(Lazy Loading,v15+) |
loadChildren | 动态导入函数,返回子路由数组(模块级懒加载) |
children | 嵌套子路由配置 |
canActivate | 路由激活守卫 |
canActivateChild | 子路由激活守卫 |
canDeactivate | 路由离开守卫 |
canMatch | 路由匹配守卫(v14.2+,替代已废弃的 canLoad) |
resolve | 数据预取解析器 |
data | 静态路由数据 |
redirectTo | 重定向目标(v20 起支持异步函数) |
title | 页面标题(配合 TitleStrategy) |
outlets | 命名Outlet路由 |
三种组件加载模式
// 1. Eager Loading — 应用启动时立即加载
{ path: 'home', component: HomeComponent }
// 2. Lazy Loading 组件 — 按需加载独立组件(v15+ Standalone)
{ path: 'about', loadComponent: () => import('./about.component').then(m => m.AboutComponent) }
// 3. Lazy Loading 子路由 — 按需加载整棵子路由树
{ path: 'admin', loadChildren: () => import('./admin.routes').then(m => m.ADMIN_ROUTES) }懒加载函数运行在当前路由的注入上下文中,可以使用 inject() 访问服务实现动态加载决策:
{
path: 'dashboard',
loadComponent: () => {
const flags = inject(FeatureFlags)
return flags.isPremium
? import('./premium-dashboard.component')
: import('./basic-dashboard.component')
},
}路由守卫(Guards)
Angular Router 提供五种路由守卫,从 v15 起推荐使用函数式守卫(*Fn 类型):
import { inject } from '@angular/core'
import { CanActivateFn, CanDeactivateFn, CanMatchFn, ResolveFn, Router } from '@angular/router'
// 1. canActivate — 控制是否可进入路由
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService)
const router = inject(Router)
return authService.isAuthenticated()
? true
: router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } })
}
// 2. canDeactivate — 控制是否可离开路由(如未保存表单)
export const unsavedGuard: CanDeactivateFn<FormGroup> = (component) => {
return component.isDirty
? window.confirm('有未保存的更改,确定离开吗?')
: true
}
// 3. canMatch — 控制路由是否参与匹配(替代废弃的 canLoad)
export const featureFlagGuard: CanMatchFn = (route, segments) => {
const flags = inject(FeatureFlags)
return flags.isEnabled(route.data?.['featureKey'] ?? '')
}
// 4. resolve — 路由激活前预取数据
export const userResolver: ResolveFn<User> = (route) => {
const userService = inject(UserService)
return userService.getUser(route.paramMap.get('id')!)
}
// 5. canActivateChild — 控制子路由激活
export const childAuthGuard: CanActivateChildFn = (route, state) => {
return inject(AuthService).isAuthenticated()
}路由事件流
Angular Router 通过 Router.events 暴露完整的 RxJS Observable 导航事件流:
import { inject } from '@angular/core'
import { Router, NavigationStart, NavigationEnd, NavigationError } from '@angular/router'
import { filter, pairwise } from 'rxjs'
const router = inject(Router)
// 监听导航结束事件
router.events.pipe(
filter((e): e is NavigationEnd => e instanceof NavigationEnd),
).subscribe(event => {
console.log('Navigation ended to:', event.urlAfterRedirects)
})
// 导航错误处理
router.events.pipe(
filter((e): e is NavigationError => e instanceof NavigationError),
).subscribe(event => {
console.error('Navigation error:', event.error)
})事件类型包括:NavigationStart、NavigationEnd、NavigationCancel、NavigationError、NavigationSkipped、RoutesRecognized、GuardsCheckStart、GuardsCheckEnd、ResolveStart、ResolveEnd、ActivationStart、ActivationEnd、RouteConfigLoadStart、RouteConfigLoadEnd、Scroll。
预加载策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
NoPreloading | 默认,不预加载任何懒加载模块 | 带宽敏感的应用 |
PreloadAllModules | 初始加载完成后预加载所有懒加载模块 | 内网/企业应用 |
QuicklinkStrategy | 仅预加载视口中可见链接对应的模块(ngx-quicklink) | 公网应用,平衡体验与带宽 |
| 自定义策略 | 实现 PreloadingStrategy 接口,按条件预加载 | 基于用户角色/行为的智能预加载 |
// 自定义预加载策略示例
import { PreloadingStrategy, Route } from '@angular/router'
import { Observable, of } from 'rxjs'
export class SelectivePreloadingStrategy extends PreloadingStrategy {
preload(route: Route, load: () => Observable<unknown>): Observable<unknown> {
// 仅预加载标记了 data: { preload: true } 的路由
return route.data?.['preload'] ? load() : of(null)
}
}
// 配置
provideRouter(routes, withPreloading(SelectivePreloadingStrategy))v19/v20/v21/v22 路由重大变化
Angular v19(2024年11月)
- SSR 路由渲染配置:支持按路由配置 SSR 渲染方式(服务端/客户端)
- Signal-based Resource API:路由 Resolve 支持 Signal 资源,防止竞态条件
- HMR 支持:样式热替换稳定,模板热替换实验性支持
Angular v20(2025年5月)
- 导航取消 API:
Router.getCurrentNavigation()?.abort()可编程取消正在进行的导航 - 异步重定向:
redirectTo支持返回Promise或Observable:{ path: '**', redirectTo: () => { const authService = inject(AuthService) return authService.checkAuth().then(isAuth => isAuth ? '/dashboard' : '/login' ) }, } - View Transitions API:
withViewTransitions()启用浏览器原生路由切换动画 - 子路由 Resolve 访问父级数据:子路由 Resolve 可读取父路由已解析的数据
- 自定义元素作为 RouterLink Host:Web Component 可作为 RouterLink 宿主
- ViewportScroller 平滑滚动:
scrollToPosition({ behavior: 'smooth' })
Angular v20.2(2025年8月)
currentNavigationSignal:替代废弃的Router.getCurrentNavigation()方法,提供响应式导航状态:import { Router } from '@angular/router' import { toSignal } from '@angular/core/rxjs-interop' const router = inject(Router) // 新的 Signal API(推荐) const navigation = router.currentNavigation // Signal<Navigation | null>- Zoneless 兼容:Router 在 Zoneless 应用中完全稳定
Angular v21(2025年11月)
isActive()独立函数:创建计算 Signal 追踪 URL 激活状态:import { isActive } from '@angular/router' const isHomeActive = isActive('/home', { exact: true })- 路由与 Signals 集成进一步深化
Angular v22(2026年6月)
- 稳定性版本:多个路由相关 API 从 Developer Preview 转为 Stable
- Signal Forms 与路由表单的深度集成
- Angular Aria 改善路由可访问性
核心特性
- 模块/组件懒加载:基于 ES 动态
import()的按需加载,支持组件级(loadComponent)和路由树级(loadChildren)粒度 - 五层路由守卫:canActivate、canActivateChild、canDeactivate、canMatch、resolve,全面控制路由访问和数据预取
- 函数式守卫与解析器:v15+ 的
CanActivateFn、ResolveFn等,配合inject()简化实现 - 智能预加载策略:内置
PreloadAllModules、NoPreloading,支持自定义PreloadingStrategy和第三方 QuicklinkStrategy - View Transitions API 集成:v17+ 通过
withViewTransitions()启用浏览器原生路由切换动画 - 路由组件输入绑定:
withComponentInputBinding()自动将路由参数/数据绑定到组件@Input()或 Signalinput() - 完整路由事件流:RxJS Observable 事件流覆盖导航全生命周期,支持细粒度拦截
- 嵌套路由与布局路由:支持多层嵌套路由、辅助 Outlet(Auxiliary Router Outlet)和布局路由模式
- 路由复用策略:
RouteReuseStrategy控制组件在导航时的复用/重建行为 - 异步重定向:v20+ 的
redirectTo支持异步函数,可基于服务调用决定重定向目标 - 导航取消 API:v20+ 的
Router.getCurrentNavigation()?.abort()和 v20.2+ 的currentNavigationSignal - SSR 路由渲染:配合 Angular SSR 支持按路由配置服务端/客户端渲染策略
- 滚动恢复:内置滚动位置恢复和锚点平滑滚动
- 路由标题策略:
TitleStrategy动态设置页面标题,支持 SEO - 自定义 URL 匹配:
UrlMatcher函数支持非标准 URL 匹配规则 - Zoneless 兼容:v20.2+ Router 在 Zoneless 应用中完全稳定运行
生态图
关键依赖
- @angular/core:Angular 核心框架(依赖注入、变更检测、Signals)
- @angular/common:通用工具(Location 服务、LocationStrategy)
- rxjs:响应式编程库(路由事件流、守卫/解析器返回值)
- zone.js:变更检测基础(Zoneless 模式下不需要)
Angular 生态整合
- Angular CLI:项目脚手架,自动生成路由配置和守卫文件
- Angular DevTools:浏览器扩展,路由树可视化、导航追踪
- Angular SSR / Angular DevKit:服务端渲染,增量水合(Incremental Hydration)
- Angular Material:UI 组件库,与路由动画集成
- Nx:企业级 Angular Monorepo 工具,路由生成器和模块联邦支持
相关插件与扩展
| 插件 | 功能 |
|---|---|
| @ngrx/router-store | NgRx 状态管理与路由状态同步 |
| ngx-quicklink | QuicklinkStrategy,基于视口可见性智能预加载 |
| @ngx-loading-bar/router | 路由切换时的顶部加载进度条 |
| @ngx-translate/core | 多语言国际化与路由集成 |
| @angular/service-worker | PWA 路由缓存与离线支持 |
| angular-sentry | 路由错误上报与追踪 |
| @ngneat/transloco | 高性能国际化方案的路由集成 |
社区生态
- 大量企业级权限控制方案(角色守卫、权限守卫、多因素认证守卫)
- 多语言路由方案(URL 前缀
/zh/、子域名路由) - 路由级代码分割与 Module Federation 微前端
- Google Analytics / Mixpanel 路由追踪集成
- OpenTelemetry 路由导航追踪(2026年新增方案)
适用场景
- Angular 企业级应用:Angular Router 是 Angular 项目的唯一路由方案,深度集成依赖注入和变更检测
- 大型后台管理系统:多层嵌套路由、
canMatch+canActivate实现精细权限控制、loadChildren实现模块懒加载 - 多角色/多权限系统:函数式守卫组合实现 RBAC/ABAC 权限模型,
canMatch控制路由可见性 - 复杂表单流程:
canDeactivate守卫防止意外丢失未保存数据,支持多步骤向导流程 - 微前端架构:Angular Module Federation + Angular Router 组合,实现独立部署的子应用路由
- PWA 应用:与 Service Worker 配合的离线路由支持和缓存策略
- 多语言国际化应用:路由级语言前缀、
TitleStrategy本地化标题 - SSR/SSG 应用:Angular SSR 按路由配置渲染策略,配合增量水合优化首屏性能
开发与工程化
开发流程
# 创建项目(含路由)
ng new my-app --routing --style=scss
# 开发服务器
ng serve
# 构建(开发环境)
ng build
# 生产构建(含 AOT、Tree-shaking、代码压缩)
ng build --configuration production
# 运行测试
ng test
# E2E 测试
ng e2e
# 分析构建产物
ng build --stats-json && npx webpack-bundle-analyzer dist/my-app/stats.json推荐项目结构
src/
├── app/
│ ├── app.routes.ts # 根路由配置
│ ├── app.config.ts # 应用配置(provideRouter)
│ ├── app.component.ts # 根组件
│ ├── features/ # 功能模块
│ │ ├── home/
│ │ │ ├── home.component.ts
│ │ │ └── home.routes.ts # 功能路由
│ │ ├── users/
│ │ │ ├── users.routes.ts
│ │ │ ├── resolvers/
│ │ │ │ └── user.resolver.ts
│ │ │ └── components/
│ │ └── admin/
│ │ ├── admin.routes.ts
│ │ └── guards/
│ ├── shared/ # 共享资源
│ │ ├── guards/
│ │ │ ├── auth.guard.ts
│ │ │ └── role.guard.ts
│ │ └── resolvers/
│ └── layouts/ # 布局组件
│ ├── main-layout.component.ts
│ └── auth-layout.component.ts
├── environments/
└── main.ts
布局路由模式
// app.routes.ts — 使用布局路由组织不同区域的页面
export const routes: Routes = [
{
path: '',
loadComponent: () =>
import('./layouts/main-layout.component').then(m => m.MainLayoutComponent),
children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{
path: 'home',
loadChildren: () =>
import('./features/home/home.routes').then(m => m.HOME_ROUTES),
},
{
path: 'users',
loadChildren: () =>
import('./features/users/users.routes').then(m => m.USER_ROUTES),
},
],
},
{
// 登录/注册使用独立布局(无侧边栏/导航)
path: '',
loadComponent: () =>
import('./layouts/auth-layout.component').then(m => m.AuthLayoutComponent),
children: [
{
path: 'login',
loadComponent: () =>
import('./features/auth/login.component').then(m => m.LoginComponent),
},
],
},
{ path: '**', redirectTo: 'home' },
]路由测试
import { TestBed, fakeAsync, tick } from '@angular/core/testing'
import { provideRouter, Router } from '@angular/router'
import { provideLocationMocks } from '@angular/common/testing'
import { AppComponent } from './app.component'
describe('Routing', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
providers: [
provideRouter([
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: AppComponent },
]),
provideLocationMocks(),
],
}).compileComponents()
})
it('should navigate to home', fakeAsync(() => {
const router = TestBed.inject(Router)
const fixture = TestBed.createComponent(AppComponent)
router.navigate(['/home'])
tick()
fixture.detectChanges()
expect(router.url).toBe('/home')
}))
})CI/CD 集成
- 构建部署:Angular CLI 标准构建流程,
ng build --configuration production - Nginx 配置:需要配置
try_files $uri $uri/ /index.html以支持 SPA 路由 - Docker 多阶段构建:Node.js 构建 + Nginx 运行
- SSR 部署:Angular SSR 需要 Node.js 运行服务器
- CDN 配置:静态资源使用 CDN,
index.html从源站返回
性能与安全
性能特点
- 懒加载代码分割:按需加载路由组件/模块,初始包体积可减少 50-70%
- 预加载策略:空闲时预加载后续可能需要的路由模块,消除二次导航延迟
- 路由复用:
RouteReuseStrategy避免组件重复创建销毁,缓存复杂页面状态 - AOT 编译:生产构建自动进行 Ahead-of-Time 编译,减小运行时开销
- Tree-shaking:Angular CLI 自动移除未使用代码
优化建议
- 对所有非根路由使用
loadComponent或loadChildren,避免初始包过大 - 使用
PreloadAllModules(内网)或QuicklinkStrategy(公网)预加载 - 结合
ChangeDetectionStrategy.OnPush减少路由变化引起的全树变更检测 - 使用
runGuardsAndResolvers控制守卫/解析器的触发条件(如仅参数变化时触发) - SSR 场景使用
TransferState避免客户端重复获取 Resolve 数据 - 使用
withComponentInputBinding()替代手动订阅ActivatedRoute.params,减少内存泄漏风险 - 使用
takeUntilDestroyed()管理路由相关订阅的生命周期
安全注意事项
- 路由鉴权非安全屏障:
canActivate守卫仅是前端 UX 优化,真正的安全验证必须在服务端/API 层实现 - XSS 防护:Angular 默认转义模板输出,但
bypassSecurityTrust*系列方法需要谨慎使用 - CSRF 防护:Angular 提供
HttpClientXsrfModule处理 CSRF Token - 路由参数验证:对用户输入的路由参数(
:id、queryParams)进行类型和范围验证 - 开放重定向防护:登录后的
returnUrl重定向需要白名单验证,防止钓鱼攻击 - 敏感路由 noindex:登录后页面、管理页面设置
noindex防止搜索引擎索引
已知性能瓶颈
- 大量路由配置的初始解析时间(数百条路由时可能影响启动速度)
- 复杂守卫逻辑(如多个异步 API 调用)可能阻塞导航
- 深层嵌套路由的递归变更检测(配合 OnPush 缓解)
- 懒加载模块的首次导航延迟(可通过预加载缓解)
RouteReuseStrategy使用不当导致内存泄漏(缓存组件未释放)Router.events订阅未取消导致的内存泄漏
技术对比
| 特性 | Angular Router (v22) | React Router v7 | Vue Router 4 | TanStack Router |
|---|---|---|---|---|
| 框架绑定 | Angular 专属 | React 专属 | Vue 3 专属 | React 专属 |
| 内置/独立 | 框架内置 | 独立库 | 独立库(官方推荐) | 独立库 |
| 包体积 | ~55KB gzipped | ~45KB gzipped | ~18KB gzipped | ~30KB gzipped |
| 懒加载 | ✅ 组件级 + 路由树级 | ✅ 组件级 | ✅ 组件级 | ✅ 组件级 |
| 路由守卫 | ✅ 五种内置守卫 | ⚠️ 需 loader 手动实现 | ✅ 全局/路由/组件三层 | ✅ beforeLoad |
| 预加载策略 | ✅ 可定制策略 + Quicklink | ✅ prefetch 意图预加载 | ❌ 无内置策略 | ✅ 悬停/意图预加载 |
| 数据预取 | ✅ Resolve 守卫 | ✅ Loader API | ❌ 需手动实现 | ✅ Loader API |
| 路由动画 | ✅ View Transitions API | ❌ 需 CSS/第三方 | ✅ Transition 组件 | ❌ 需 CSS |
| 响应式事件 | ✅ RxJS 完整事件流 | ❌ 无 | ❌ 无 | ❌ 无 |
| 类型安全路由路径 | ⚠️ 字符串路径 | ⚠️ 部分泛型 | ⚠️ 部分泛型 | ✅ 端到端类型安全 |
| Signal 集成 | ✅ currentNavigation Signal | ❌ 无 | ⚠️ 实验性 | ❌ 无 |
| SSR 支持 | ✅ Angular SSR + 增量水合 | ✅ 完整(框架级) | ⚠️ 基础 | ✅ 支持 |
| 导航取消 | ✅ abort() API | ⚠️ 需手动 | ❌ 无 | ❌ 无 |
| 学习曲线 | 较陡 | 低 | 低 | 中等 |
| 社区生态 | 企业级方案丰富 | 生态最大 | 中等规模 | 快速增长 |
最佳实践
路由模块化与懒加载
// ✅ 推荐:按功能模块拆分路由,全部使用懒加载
export const routes: Routes = [
{
path: '',
loadComponent: () =>
import('./layouts/main-layout.component').then(m => m.MainLayoutComponent),
children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{
path: 'home',
loadChildren: () =>
import('./features/home/home.routes').then(m => m.HOME_ROUTES),
},
{
path: 'users',
loadChildren: () =>
import('./features/users/users.routes').then(m => m.USER_ROUTES),
},
],
},
{ path: '**', redirectTo: 'home' },
]函数式守卫组合
// ✅ 推荐:使用函数式守卫 + inject() + 组合模式
const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService)
const router = inject(Router)
if (!authService.isAuthenticated()) {
return router.createUrlTree(['/login'], {
queryParams: { returnUrl: state.url },
})
}
return true
}
const adminGuard: CanActivateFn = () => {
const authService = inject(AuthService)
const router = inject(Router)
return authService.user()?.role === 'admin'
? true
: router.createUrlTree(['/forbidden'])
}
// 路由配置中组合多个守卫
{
path: 'admin',
canActivate: [authGuard, adminGuard],
loadChildren: () => import('./admin.routes').then(m => m.ADMIN_ROUTES),
}数据预取与组件输入绑定
// ✅ 推荐:使用 Resolve + withComponentInputBinding 替代手动订阅
const userResolver: ResolveFn<User> = (route) => {
const userService = inject(UserService)
return userService.getUser(route.paramMap.get('id')!)
}
// 路由配置
{
path: 'users/:id',
resolve: { user: userResolver },
loadComponent: () =>
import('./user-detail.component').then(m => m.UserDetailComponent),
}
// 组件 — 通过 @Input 直接接收路由参数和 Resolve 数据
@Component({ /* ... */ })
export class UserDetailComponent {
@Input() id!: string // 来自路由参数 :id
@Input() user!: User // 来自 resolve: { user: userResolver }
}
// ✅ v17+ 更推荐:使用 Signal input
@Component({ /* ... */ })
export class UserDetailComponent {
id = input.required<string>()
user = input.required<User>()
}导航事件与加载状态
// ✅ 推荐:使用 currentNavigation Signal(v20.2+)追踪导航状态
@Component({
selector: 'app-loading-bar',
template: `<div class="bar" [class.active]="isNavigating()"></div>`,
})
export class LoadingBarComponent {
private router = inject(Router)
isNavigating = computed(() => this.router.currentNavigation() !== null)
}常见陷阱
- ❌ 不要使用
component替代loadComponent(失去懒加载能力,增大初始包体积) - ❌ 不要忽略
pathMatch: 'full'(空路径重定向缺少它会导致所有路由匹配) - ❌ 不要在守卫中执行耗时同步操作(阻塞 UI 线程)
- ❌ 不要忘记取消
Router.events和ActivatedRoute.params的订阅(使用takeUntilDestroyed()) - ❌ 不要在
RouteReuseStrategy中缓存过多组件(导致内存泄漏) - ❌ 不要将前端路由守卫当作安全屏障(服务端必须做权限校验)
- ❌ 不要在
canDeactivate中依赖已被销毁的组件引用 - ❌ 不要混用
RouterModule.forRoot()和provideRouter()(选一种配置方式)
技术局限与边界
已知限制
- Angular 专属:只能用于 Angular 项目,无法跨框架复用路由逻辑
- 学习曲线陡峭:概念体系复杂(模块、守卫、解析器、预加载策略、复用策略、URL 匹配器等)
- 包体积较大:相比 Vue Router(~18KB)等,Angular Router 体积较大(~55KB),但这是 Angular 整体体积的一部分
- 路由路径无编译期类型安全:路径是字符串字面量,重构时可能遗漏(TanStack Router 提供了端到端类型安全)
- 与 Angular 版本强绑定:路由 API 随框架版本升级变化,大版本迁移需要同步更新路由配置
- Zone.js 依赖:传统模式下依赖 Zone.js 触发变更检测(v20.2+ 支持 Zoneless 但仍在演进中)
不适用场景
- 非 Angular 项目(React/Vue/Svelte 等框架)
- 极简单的单页面应用(1-3 个页面,无导航需求)
- 对包体积极度敏感的边缘场景(Angular 整体包体积较大)
- 需要跨框架共享路由逻辑的微前端场景(需用其他方案处理路由协调)
- 需要端到端类型安全路由路径的场景(TanStack Router 更优)
迁移注意事项
| 迁移方向 | 要点 |
|---|---|
| NgModule → Standalone | RouterModule.forRoot() → provideRouter(),移除 @NgModule 装饰器 |
| 类守卫 → 函数守卫 | CanActivate 类 → CanActivateFn 函数,使用 inject() 获取依赖 |
canLoad → canMatch | v14.2+ 废弃 canLoad,使用 canMatch 替代 |
getCurrentNavigation() → Signal | v20.2+ 废弃方法,使用 router.currentNavigation Signal |
| 手动订阅 → 输入绑定 | 使用 withComponentInputBinding() 替代手动订阅 ActivatedRoute.params |
| Angular 版本升级 | 每个大版本检查废弃 API 和 Breaking Changes |
学习资源
官方文档
- Angular Router 概览 — 官方路由指南入口
- 路由加载策略 — 懒加载、预加载详解
- 路由守卫与解析器 — 守卫与动画
- Router API 参考 — 完整 API 文档
- Angular 路线图 — 官方版本规划
教程
- Angular 官方教程 — Learn Angular
- Angular University — Routing 深度课程
- Lunatech — Routing in Angular 20
- Angular Architects — Standalone Components 路由
- web.dev — Route Preloading Strategies
社区资源
- Angular Discord 官方服务器
- Stack Overflow #angular 标签
- Reddit r/Angular2
- Angular YouTube 官方频道
- Angular.love 社区博客
- ng-conf YouTube 频道
- Angular DevTools 浏览器扩展
2026 年现状
最新版本
- Angular 22.0.5(2026年6月3日发布)— 当前最新稳定版
- @angular/router 22.0.5 — 与框架同步发版
- Angular 21.x(2025年11月)— 仍在 LTS 支持期内
- Angular 20.x(2025年5月)— LTS 支持中
- Angular 19.x — 已于 2026年5月到达 EOL
发展趋势
- Signals 全面渗透:路由状态(
currentNavigation)、URL 激活追踪(isActive)、表单集成(Signal Forms)全面 Signal 化 - Zoneless 稳定化:Router 在 Zoneless 模式下完全稳定,不再依赖
zone.js - SSR + 增量水合:Angular SSR 持续增强,按路由配置渲染策略,增量水合稳定后进一步提升首屏性能
- View Transitions 成熟:浏览器原生 View Transitions API 在更多浏览器中支持,Angular Router 集成日趋成熟
- AI 工具集成:Angular CLI 内置 MCP 配置生成,AI 辅助路由配置和调试
社区活跃度
- GitHub Stars(Angular 整体):约 98k+
- npm 周下载量(@angular/router):约 350 万+
- 贡献者(Angular 整体):2000+
- 更新频率:每 6 个月一个主版本(5月/11月)
- Angular v22 被社区评价为"2026年最佳 JavaScript 框架更新之一"
未来路线图
- Signals 在路由模块中的全面应用(路由配置 Signal 化)
- 更简洁的路由配置 API 和类型安全增强
- SSR 和增量水合的持续改进,支持更多渲染策略
- 浏览器 View Transitions API 跨浏览器兼容完善
- 开发工具(DevTools)路由可视化增强
- 与 Angular 框架统一演进,保持 6 个月发版节奏