angular-routing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Angular Routing - Quick Reference

Angular 路由 - 速查指南

Deep Knowledge: Use
mcp__documentation__fetch_docs
with technology:
angular
, topic:
routing
for comprehensive documentation.
深度资料:如需完整文档,请使用
mcp__documentation__fetch_docs
,指定技术:
angular
,主题:
routing

Route Configuration (Standalone)

独立式路由配置

typescript
// app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
  {
    path: 'dashboard',
    loadComponent: () => import('./features/dashboard/dashboard.component')
      .then(m => m.DashboardComponent),
  },
  {
    path: 'users',
    loadChildren: () => import('./features/users/users.routes')
      .then(m => m.USERS_ROUTES),
    canActivate: [authGuard],
  },
  { path: '**', loadComponent: () => import('./not-found.component').then(m => m.NotFoundComponent) },
];
typescript
// app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
  {
    path: 'dashboard',
    loadComponent: () => import('./features/dashboard/dashboard.component')
      .then(m => m.DashboardComponent),
  },
  {
    path: 'users',
    loadChildren: () => import('./features/users/users.routes')
      .then(m => m.USERS_ROUTES),
    canActivate: [authGuard],
  },
  { path: '**', loadComponent: () => import('./not-found.component').then(m => m.NotFoundComponent) },
];

Lazy Loading Feature Routes

特性路由懒加载

typescript
// features/users/users.routes.ts
import { Routes } from '@angular/router';

export const USERS_ROUTES: Routes = [
  {
    path: '',
    loadComponent: () => import('./user-list.component').then(m => m.UserListComponent),
  },
  {
    path: ':id',
    loadComponent: () => import('./user-detail.component').then(m => m.UserDetailComponent),
    resolve: { user: userResolver },
  },
];
typescript
// features/users/users.routes.ts
import { Routes } from '@angular/router';

export const USERS_ROUTES: Routes = [
  {
    path: '',
    loadComponent: () => import('./user-list.component').then(m => m.UserListComponent),
  },
  {
    path: ':id',
    loadComponent: () => import('./user-detail.component').then(m => m.UserDetailComponent),
    resolve: { user: userResolver },
  },
];

Functional Guards (Angular 15+)

函数式守卫(Angular 15+)

typescript
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';

export const authGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  const router = inject(Router);

  if (authService.isAuthenticated()) {
    return true;
  }
  return router.createUrlTree(['/login']);
};

export const roleGuard: CanActivateFn = (route) => {
  const authService = inject(AuthService);
  const requiredRole = route.data['role'] as string;
  return authService.hasRole(requiredRole);
};
typescript
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';

export const authGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  const router = inject(Router);

  if (authService.isAuthenticated()) {
    return true;
  }
  return router.createUrlTree(['/login']);
};

export const roleGuard: CanActivateFn = (route) => {
  const authService = inject(AuthService);
  const requiredRole = route.data['role'] as string;
  return authService.hasRole(requiredRole);
};

Functional Resolvers

函数式解析器

typescript
import { inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { UserService } from './user.service';
import { User } from './user.model';

export const userResolver: ResolveFn<User> = (route) => {
  const userService = inject(UserService);
  const id = Number(route.paramMap.get('id'));
  return userService.getById(id);
};
typescript
import { inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { UserService } from './user.service';
import { User } from './user.model';

export const userResolver: ResolveFn<User> = (route) => {
  const userService = inject(UserService);
  const id = Number(route.paramMap.get('id'));
  return userService.getById(id);
};

Route Parameters with Input Binding

路由参数与输入绑定

typescript
// Enable in app.config.ts: provideRouter(routes, withComponentInputBinding())

@Component({ standalone: true, template: `<p>User {{ id }}</p>` })
export class UserDetailComponent {
  @Input() id!: string; // Automatically bound from :id route param
}
typescript
// 在app.config.ts中启用:provideRouter(routes, withComponentInputBinding())

@Component({ standalone: true, template: `<p>用户 {{ id }}</p>` })
export class UserDetailComponent {
  @Input() id!: string; // 自动绑定自:id路由参数
}

Navigation

导航

typescript
import { Router, RouterLink } from '@angular/router';

// Template
// <a [routerLink]="['/users', user.id]">View User</a>
// <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>

// Programmatic
@Component({ ... })
export class SomeComponent {
  private router = inject(Router);

  navigate() {
    this.router.navigate(['/users', 42], {
      queryParams: { tab: 'profile' },
    });
  }
}
typescript
import { Router, RouterLink } from '@angular/router';

// 模板
// <a [routerLink]="['/users', user.id]">查看用户</a>
// <a routerLink="/dashboard" routerLinkActive="active">仪表盘</a>

// 编程式导航
@Component({ ... })
export class SomeComponent {
  private router = inject(Router);

  navigate() {
    this.router.navigate(['/users', 42], {
      queryParams: { tab: 'profile' },
    });
  }
}

Anti-Patterns

反模式

Anti-PatternWhy It's BadCorrect Approach
Eager loading all routesLarge bundle sizeUse
loadComponent
/
loadChildren
Class-based guardsVerbose, deprecated patternUse functional guards with
inject()
Subscribing to params manuallyBoilerplate, leak riskUse
withComponentInputBinding()
Nested route configs in app.routesHard to maintainSplit into feature route files
反模式问题原因正确做法
预加载所有路由包体积过大使用
loadComponent
/
loadChildren
基于类的守卫代码冗余,已被弃用使用带
inject()
的函数式守卫
手动订阅路由参数样板代码多,存在内存泄漏风险使用
withComponentInputBinding()
在app.routes中嵌套路由配置难以维护拆分到特性路由文件中

Quick Troubleshooting

快速故障排除

IssueLikely CauseSolution
Route not matchingOrder mattersPut specific routes before wildcards
Guard not triggeringNot in route configAdd to
canActivate
array
Lazy load failsWrong exportEnsure component is exported
Query params lostNavigate without preserveUse
queryParamsHandling: 'merge'
问题可能原因解决方案
路由不匹配路由顺序问题把具体路由放在通配符路由之前
守卫未触发未添加到路由配置添加到
canActivate
数组中
懒加载失败导出错误确保组件已正确导出
查询参数丢失导航时未保留参数使用
queryParamsHandling: 'merge'