前言
Router 是 Angular 中負責頁面導航的核心功能。透過 Router,我們可以實現單頁應用(SPA)的頁面切換,而不需要重新加載整個應用程式。
Router 用途
Angular Router 負責管理 Angular Web App 中的不同頁面之間的路由。透過 Router 模組提供了路由的機制,讓 Angular Web App 進行類似傳統網頁應用的導航,但不需要重新加載整個應用程式。
可以通過 RouterModule 進行自訂和訪問。通過設定路由規則可以讓 Angular 在特定的 URL 下載入特定 Component。
// path 為路徑,component 決定要載入的 Component
const routes: Routes = [{ path: "users/:id", component: UserComponent }];
基本路由設定
設定路由
在 app-routing.module.ts 或 app.config.ts 中設定路由:
// 傳統 NgModule 方式
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { HomeComponent } from "./home/home.component";
import { AboutComponent } from "./about/about.component";
import { UserComponent } from "./user/user.component";
const routes: Routes = [
{ path: "", component: HomeComponent }, // 根路徑
{ path: "about", component: AboutComponent },
{ path: "users/:id", component: UserComponent }, // 動態路由
{ path: "**", redirectTo: "" }, // 404 重新導向
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
// Standalone 方式
import { provideRouter } from "@angular/router";
export const appConfig: ApplicationConfig = {
providers: [
provideRouter([
{ path: "", component: HomeComponent },
{ path: "about", component: AboutComponent },
{ path: "users/:id", component: UserComponent },
]),
],
};
使用 Router Outlet
在主要的 Template 中加入 <router-outlet>:
<nav>
<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
<a routerLink="/users/1">User 1</a>
</nav>
<router-outlet></router-outlet>
RouterLink
使用 routerLink 指令進行導航:
<!-- 基本使用 -->
<a routerLink="/about">About</a>
<!-- 帶參數 -->
<a [routerLink]="['/users', userId]">User Profile</a>
<!-- 帶 Query Parameters -->
<a [routerLink]="['/search']" [queryParams]="{q: 'angular'}">Search</a>
<!-- Active 樣式 -->
<a routerLink="/about" routerLinkActive="active">About</a>
路由參數
取得路由參數
在 Component 中取得路由參數:
import { ActivatedRoute } from "@angular/router";
export class UserComponent implements OnInit {
userId: string;
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
// 方式 1:snapshot(快照)
this.userId = this.route.snapshot.paramMap.get("id");
// 方式 2:Observable(推薦,支援參數變化)
this.route.paramMap.subscribe((params) => {
this.userId = params.get("id");
this.loadUserData(this.userId);
});
}
}
Query Parameters
// 設定 Query Parameters
this.router.navigate(["/search"], { queryParams: { q: "angular", page: 1 } });
// 取得 Query Parameters
this.route.queryParamMap.subscribe((params) => {
const query = params.get("q");
const page = params.get("page");
});
程式化導航
使用 Router 服務進行程式化導航:
import { Router } from "@angular/router";
export class MyComponent {
constructor(private router: Router) {}
goToAbout(): void {
this.router.navigate(["/about"]);
}
goToUser(id: number): void {
this.router.navigate(["/users", id]);
}
goBack(): void {
// 使用 Location 服務返回上一頁
this.location.back();
}
}
路由守衛(Route Guards)
路由守衛用於控制路由的訪問權限。
CanActivate
保護路由,決定是否可以進入。
import { Injectable } from "@angular/core";
import { CanActivate, Router } from "@angular/router";
@Injectable({ providedIn: "root" })
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.router.navigate(["/login"]);
return false;
}
}
使用守衛:
const routes: Routes = [
{
path: "admin",
component: AdminComponent,
canActivate: [AuthGuard],
},
];
CanDeactivate
決定是否可以離開當前路由。
export interface CanComponentDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
@Injectable({ providedIn: "root" })
export class CanDeactivateGuard
implements CanDeactivate<CanComponentDeactivate>
{
canDeactivate(
component: CanComponentDeactivate
): boolean | Observable<boolean> {
return component.canDeactivate();
}
}
子路由(Child Routes)
建立嵌套路由結構:
const routes: Routes = [
{
path: "products",
component: ProductsComponent,
children: [
{ path: "", component: ProductListComponent },
{ path: ":id", component: ProductDetailComponent },
{ path: ":id/edit", component: ProductEditComponent },
],
},
];
在父 Component 的 Template 中:
<h2>Products</h2>
<router-outlet></router-outlet>
懶加載(Lazy Loading)
使用懶加載減少初始載入時間:
const routes: Routes = [
{
path: "admin",
loadChildren: () =>
import("./admin/admin.module").then((m) => m.AdminModule),
},
// Standalone 方式
{
path: "shop",
loadComponent: () =>
import("./shop/shop.component").then((m) => m.ShopComponent),
},
];
路由事件
監聽路由變化:
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
constructor(private router: Router) {
this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
console.log('Navigation started');
}
if (event instanceof NavigationEnd) {
console.log('Navigation ended');
}
});
}
總結
Angular Router 提供了完整的路由解決方案:
- 基本路由:設定路徑與 Component 的對應關係
- 路由參數:支援動態路由和 Query Parameters
- 程式化導航:使用 Router 服務進行導航
- 路由守衛:控制路由訪問權限
- 子路由:建立嵌套路由結構
- 懶加載:優化應用程式載入效能
掌握 Angular Router 可以讓你建立複雜的單頁應用,提供流暢的使用者體驗。