嵌套路由(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',
      })
    ),
  ],
};

使用場景與優勢

嵌套路由最常見的使用場景包括:

  1. 主/次內容結構:如儀表板應用,主視圖顯示概覽資訊,子路由展示詳細資料

  2. 多步驟表單或流程:父路由包含整體流程 UI,子路由顯示每個步驟的表單

  3. 複雜的資料導航:如郵件應用,左側固定顯示郵件列表,右側通過子路由顯示選中的郵件內容

嵌套路由的主要優勢:

  • 減少重複的 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

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

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

Last updated