嵌套路由(Nested Routes)
基本概念
嵌套路由(也稱為子路由, child routes)是 Angular 路由系統的一個特殊功能,它允許我們使用嵌套的 router outlets,使得一個元件可以載入到因為另一條路由而已載入的另一個元件中。
簡單來說,嵌套路由讓我們能夠在已渲染的元件內部指定第二個(或更多)路由區域,從而建立更複雜的視圖層次結構。
設定方法
嵌套路由通過在路由配置中使用 children
屬性來設定:
{
path: 'users/:userId', // <your-domain>/users/<uid>
component: UserTasksComponent,
children: [
{
path: 'tasks', // <your-domain>/users/<uid>/tasks
component: TasksComponent,
},
{
path: 'tasks/new',
component: NewTaskComponent,
},
],
},
值得一提的是,在 children
屬性中設置的路徑會自動連接到父路徑上。也就是說,子路徑會自動拿父路徑並加上自己的路徑來組成完整路徑。例如:
父路徑:
/users/:userId
子路徑:
tasks
完整路徑:
/users/:userId/tasks
在父元件中加入 router-outlet
要讓嵌套路由正常工作,你必須在父路徑對應的元件模板中加入額外的 <router-outlet>
元素:
<!-- UserTasksComponent 的模板 -->
<section id="tasks">
<header>
<h2>{{ userName }} Tasks</h2>
<menu>
<a>Add Task</a>
</menu>
</header>
<!-- 子路由元件將在這裡渲染 -->
<router-outlet />
</section>
如果沒有這個 router-outlet
,Angular 不知道該把子路由元件渲染在哪裡。
在子路由中存取父路由參數
在子路由元件中,你可能需要訪問父路由的參數(如上例中的 :userId
):
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-tasks',
standalone: true,
template: `<h3>任務列表 (用戶 ID: {{userId}})</h3>`
})
export class TasksComponent implements OnInit {
userId: string = '';
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 方法1:通過父路由獲取參數
this.route.parent?.paramMap.subscribe(params => {
this.userId = params.get('userId') || '';
});
// 方法2:針對有父路由參數命名的元件輸入(Angular 16+)
// userId = input<string>();,
}
}
上面提到的獲取父路由參數的方法二,在預設情境下不會有效。需要在設置檔裡面新增 withRouterConfig({paramsInheritanceStrategy: 'always',})
設置,以確保這些動態 path 的參數值被注入到子路由中。
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(
routes,
withComponentInputBinding(),
withRouterConfig({
paramsInheritanceStrategy: 'always',
})
),
],
};
使用場景與優勢
嵌套路由最常見的使用場景包括:
主/次內容結構:如儀表板應用,主視圖顯示概覽資訊,子路由展示詳細資料
多步驟表單或流程:父路由包含整體流程 UI,子路由顯示每個步驟的表單
複雜的資料導航:如郵件應用,左側固定顯示郵件列表,右側通過子路由顯示選中的郵件內容
嵌套路由的主要優勢:
減少重複的 UI 元素(如導航列、側邊欄)
保持父元件的狀態不變
創建更直觀的 URL 結構,反映應用的層次關係
提供更好的組件重用性
補充:懶載入嵌套路由
對於大型應用,你可以結合懶載入(lazy loading)和嵌套路由:
{
path: 'admin',
loadComponent: () => import('./admin/admin.component').then(m => m.AdminComponent),
children: [
{
path: 'dashboard',
loadComponent: () => import('./admin/dashboard/dashboard.component').then(m => m.DashboardComponent),
}
]
}
這種方式可以進一步提升應用的載入效能。
注意事項
確保在父元件中添加
<router-outlet>
標籤子路由導航時使用相對路徑會更簡潔
避免過多層級的嵌套,以保持路由結構清晰
使用
routerLinkActive
來標記當前活動的子路由
http://localhost:4200/users/u2/tasks

http://localhost:4200/users/u2/tasks/new

Last updated