RouterOutlet 指令是一個預留位置,標示路由器應在此處渲染目前 URL 對應的元件。
<app-header />
<!-- Angular inserts your route content here -->
<router-outlet />
<app-footer />
import {Component} from '@angular/core';
import {RouterOutlet} from '@angular/router';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.html',
styleUrl: './app.css',
})
export class App {}
在本範例中,假設應用程式定義了下列路由:
import {Routes} from '@angular/router';
import {Home} from './home';
import {Products} from './products';
const routes: Routes = [
{
path: '',
component: Home,
title: 'Home Page',
},
{
path: 'products',
component: Products,
title: 'Our Products',
},
];
當使用者造訪 /products 時,Angular 會渲染下列內容:
<app-header />
<app-products />
<app-footer />
若使用者回到首頁,Angular 則會渲染:
<app-header />
<app-home />
<app-footer />
顯示路由時,<router-outlet> 元素會保留在 DOM 中,作為後續導覽的參照點。Angular 會把路由內容插入在 outlet 元素之後,作為其同層元素。
<!-- Contents of the component's template -->
<app-header />
<router-outlet />
<app-footer />
<!-- Content rendered on the page when the user visits /admin -->
<app-header />
<router-outlet />
<app-admin-page />
<app-footer />
使用子路由建立巢狀路由
隨著應用程式越來越複雜,你可能會想建立相對於根元件以外元件的路由。這樣一來,URL 改變時只有應用程式的一部分會跟著改變,使用者不會感覺整個頁面都被重新整理。
這類巢狀路由稱為子路由。這表示你要在應用程式中再加入第二個 <router-outlet>,因為它是在 AppComponent 的 <router-outlet> 之外額外增加的。
在本範例中,Settings 元件會依使用者選取的項目顯示對應的面板。子路由的一個特別之處是,該元件通常有自己的 <nav> 與 <router-outlet>。
<h1>Settings</h1>
<nav>
<ul>
<li><a routerLink="profile">Profile</a></li>
<li><a routerLink="security">Security</a></li>
</ul>
</nav>
<router-outlet />
子路由與其他路由一樣,都需要 path 與 component。唯一的差別是,子路由要放在父路由內的 children 陣列中。
const routes: Routes = [
{
path: 'settings',
component: Settings, // this is the component with the <router-outlet> in the template
children: [
{
path: 'profile', // child route path
component: Profile, // child route component that the router renders
},
{
path: 'security',
component: Security, // another child route component that the router renders
},
],
},
];
只要 routes 與 <router-outlet> 都設定正確,你的應用程式就已經用上巢狀路由了!
使用具名 outlet 的次要路由
一個頁面可以有多個 outlet,你可以為每個 outlet 指定名稱,表明哪些內容屬於哪個 outlet。
<app-header />
<router-outlet />
<router-outlet name="read-more" />
<router-outlet name="additional-actions" />
<app-footer />
每個 outlet 的名稱必須唯一。你可以把名稱繫結到一個值;當值改變時,outlet 會銷毀目前的元件,並在有符合的路由時,渲染新名稱對應的路由。名稱預設為 'primary'。
Angular 會把 outlet 的名稱與每條路由上定義的 outlet 屬性進行比對:
{
path: 'user/:id',
component: UserDetails,
outlet: 'additional-actions'
}
Outlet 生命週期事件
路由器 outlet 可以發出四種生命週期事件:
| 事件 | 說明 |
|---|---|
activate |
新元件被實例化時 |
deactivate |
元件被銷毀時 |
attach |
RouteReuseStrategy 指示 outlet 附加子樹時 |
detach |
RouteReuseStrategy 指示 outlet 分離子樹時 |
你可以使用標準的事件繫結語法加入事件監聽器:
<router-outlet
(activate)="onActivate($event)"
(deactivate)="onDeactivate($event)"
(attach)="onAttach($event)"
(detach)="onDetach($event)"
/>
若想深入了解,請參閱 RouterOutlet 的 API 文件。
把上下文資料傳給路由元件
把上下文資料傳給路由元件,往往需要全域狀態或複雜的路由設定。為了簡化這件事,每個 RouterOutlet 都支援 routerOutletData 輸入。路由元件及其子元件可以使用 ROUTER_OUTLET_DATA 注入權杖,把這份資料當作訊號讀取,藉此進行 outlet 專屬的設定,而不必修改路由定義。
import {Component} from '@angular/core';
import {RouterOutlet} from '@angular/router';
@Component({
selector: 'app-dashboard',
imports: [RouterOutlet],
template: `
<h2>Dashboard</h2>
<router-outlet [routerOutletData]="{layout: 'sidebar'}" />
`,
})
export class Dashboard {}
路由元件可以使用 ROUTER_OUTLET_DATA 注入所提供的 outlet 資料:
import {Component, inject, Signal} from '@angular/core';
import {ROUTER_OUTLET_DATA} from '@angular/router';
@Component({
selector: 'app-stats',
template: `<p>Stats view (layout: {{ outletData().layout }})</p>`,
})
export class Stats {
outletData = inject(ROUTER_OUTLET_DATA) as Signal<{layout: string}>;
}
當 Angular 在該 outlet 中啟用 Stats 時,它會收到 { layout: 'sidebar' } 作為注入的資料。
NOTE: 未設定 routerOutletData 輸入時,注入訊號的值預設為 undefined。
後續步驟
了解如何使用 Angular Router 導覽至路由。