Skip to content
 

Angular 路由与导航:构建单页应用的核心技术

更新: 9/4/2025字数: 0 字 时长: 0 分钟

路由是Angular单页应用(SPA)的核心机制,它允许我们在不重新加载整个页面的情况下切换视图。

一、路由基础配置

1. 基本路由设置

首先需要在主模块中配置路由:

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

const routes: Routes = [
  { path: "", component: HomeComponent },
  { path: "products", component: ProductsComponent },
  { path: "products/:id", component: ProductDetailComponent },
  { path: "about", component: AboutComponent },
  { path: "**", component: NotFoundComponent } // 404页面
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

2. 路由出口

在根组件模板中添加<router-outlet>

html
<!-- app.component.html -->
<app-header></app-header>
<router-outlet></router-outlet>
<!-- 路由内容将在这里渲染 -->
<app-footer></app-footer>

二、导航方式

1. 模板导航

使用routerLink指令:

html
<a routerLink="/">首页</a>
<a routerLink="/products">产品列表</a>
<a [routerLink]="['/products', product.id]">产品详情</a>

2. 编程式导航

在组件类中使用Router服务:

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

constructor(private router: Router) {}

navigateToProduct(id: number) {
  this.router.navigate(['/products', id]);

  // 或者带查询参数
  this.router.navigate(['/products'], {
    queryParams: { category: 'electronics' }
  });
}

三、路由参数获取

1. 路径参数

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

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  // 获取路径参数
  const id = this.route.snapshot.paramMap.get('id');

  // 或者监听参数变化
  this.route.paramMap.subscribe(params => {
    this.productId = params.get('id');
  });
}

2. 查询参数

typescript
// 获取查询参数
this.route.queryParamMap.subscribe((params) => {
  this.category = params.get("category");
});

// 导航时添加查询参数
this.router.navigate(["/products"], {
  queryParams: { category: "books" }
});

四、高级路由功能

1. 路由守卫

认证守卫示例

typescript
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
  constructor(private auth: AuthService, private router: Router) {}

  canActivate(): boolean {
    if (this.auth.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

// 在路由配置中使用
{
  path: 'admin',
  component: AdminPanelComponent,
  canActivate: [AuthGuard]
}

2. 懒加载模块

typescript
{
  path: 'dashboard',
  loadChildren: () => import('./dashboard/dashboard.module')
    .then(m => m.DashboardModule)
}

3. 预加载策略

typescript
@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      preloadingStrategy: PreloadAllModules
    })
  ]
})
export class AppRoutingModule {}

五、路由动画

1. 配置路由动画

typescript
import { trigger, transition, style, animate } from "@angular/animations";

export const routeAnimations = trigger("routeAnimations", [
  transition("* <=> *", [style({ opacity: 0 }), animate("300ms ease-in", style({ opacity: 1 }))])
]);

2. 在组件中使用

typescript
@Component({
  selector: "app-root",
  template: `
    <div [@routeAnimations]="prepareRoute(outlet)">
      <router-outlet #outlet="outlet"></router-outlet>
    </div>
  `,
  animations: [routeAnimations]
})
export class AppComponent {
  prepareRoute(outlet: RouterOutlet) {
    return outlet?.activatedRouteData?.["animation"];
  }
}

六、常见问题解答

Q1: 如何实现嵌套路由?

typescript
{
  path: 'products',
  component: ProductsComponent,
  children: [
    { path: '', component: ProductListComponent },
    { path: ':id', component: ProductDetailComponent }
  ]
}

Q2: 如何获取路由事件?

typescript
this.router.events.subscribe((event) => {
  if (event instanceof NavigationStart) {
    console.log("导航开始");
  }
  if (event instanceof NavigationEnd) {
    console.log("导航结束");
  }
});

Q3: 如何设置默认路由?

typescript
{ path: '', redirectTo: '/home', pathMatch: 'full' }

我见青山多妩媚,料青山见我应如是。