路由重新導向讓你能自動將使用者從一個路由導覽至另一個路由。可以把它想像成郵件轉送:寄往某個地址的郵件,會被送到另一個不同的地址。這在處理舊有 URL、實作預設路由,或管理存取控制時非常有用。
如何設定重新導向
你可以在路由設定中,以 redirectTo 屬性定義重新導向。這個屬性接受一個字串。
import {Routes} from '@angular/router';
const routes: Routes = [
// Simple redirect
{path: 'marketing', redirectTo: 'newsletter'},
// Redirect with path parameters
{path: 'legacy-user/:id', redirectTo: 'users/:id'},
// Redirect any other URLs that don’t match
// (also known as a "wildcard" redirect)
{path: '**', redirectTo: '/login'},
];
在這個範例中,一共有三個重新導向:
- 當使用者造訪
/marketing路徑時,他們會被重新導向至/newsletter。 - 當使用者造訪任何
/legacy-user/:id路徑時,他們會被導向至對應的/users/:id路徑。 - 當使用者造訪任何未在路由器中定義的路徑時,由於
**萬用字元路徑定義,他們會被重新導向至登入頁面。
了解 pathMatch
路由上的 pathMatch 屬性,讓開發者能控制 Angular 如何將 URL 與路由進行比對。
pathMatch 可以接受兩個值:
| Value | 說明 |
|---|---|
'full' |
整個 URL 路徑必須完全相符 |
'prefix' |
只有 URL 的開頭部分需要相符 |
在預設情況下,所有重新導向都會使用 prefix 策略。
pathMatch: 'prefix'
pathMatch: 'prefix' 是預設策略,當你希望 Angular Router 在觸發重新導向時比對所有後續路由時,這個策略非常適合。
export const routes: Routes = [
// This redirect route is equivalent to…
{path: 'news', redirectTo: 'blog'},
// This explicitly defined route redirect pathMatch
{path: 'news', redirectTo: 'blog', pathMatch: 'prefix'},
];
在這個範例中,所有以 news 為前綴的路由,都會被重新導向至它們對應的 /blog 路徑。以下是使用者造訪舊的 news 前綴時被重新導向的一些範例:
/news重新導向至/blog/news/article重新導向至/blog/article/news/article/:id重新導向至/blog/article/:id
pathMatch: 'full'
另一方面,當你希望 Angular Router 只重新導向某個特定路徑時,pathMatch: 'full' 非常有用。
export const routes: Routes = [{path: '', redirectTo: '/dashboard', pathMatch: 'full'}];
在這個範例中,每當使用者造訪根 URL(即 '')時,路由器就會將該名使用者重新導向至 '/dashboard' 頁面。
任何後續頁面(例如 /login、/about、/product/id 等),都不會被納入考量,也不會觸發重新導向。
TIP: 在根頁面(即 "/" 或 "")上設定重新導向時要小心。如果你沒有設定 pathMatch: 'full',路由器將會重新導向所有的 URL。
進一步說明,如果前一節的 news 範例改用 pathMatch: 'full':
export const routes: Routes = [{path: 'news', redirectTo: '/blog', pathMatch: 'full'}];
這意味著:
- 只有
/news路徑會被重新導向至/blog。 - 任何後續區段,例如
/news/articles或/news/articles/1,都不會使用新的/blog前綴進行重新導向。
條件式重新導向
redirectTo 屬性也可以接受一個函式,藉此為使用者的重新導向方式加入邏輯。
在路由比對階段中,有些資料並無法準確得知,因此這個函式只能存取 ActivatedRouteSnapshot 的部分資料。舉例來說,這些資料包括:已解析的標題、延遲載入的元件等等。
它通常回傳一個字串或 URLTree,但也可以回傳一個 observable 或 promise。
以下範例中,使用者會根據一天中的時間,被重新導向至不同的選單:
import {Routes} from '@angular/router';
import {Menu} from './menu';
export const routes: Routes = [
{
path: 'restaurant/:location/menu',
pathMatch: 'full',
redirectTo: (activatedRouteSnapshot) => {
const location = activatedRouteSnapshot.params['location'];
const currentHour = new Date().getHours();
// Check if user requested a specific meal via query parameter
if (activatedRouteSnapshot.queryParams['meal']) {
return `/restaurant/${location}/menu/${activatedRouteSnapshot.queryParams['meal']}`;
}
// Auto-redirect based on time of day
if (currentHour >= 5 && currentHour < 11) {
return `/restaurant/${location}/menu/breakfast`;
} else if (currentHour >= 11 && currentHour < 17) {
return `/restaurant/${location}/menu/lunch`;
} else {
return `/restaurant/${location}/menu/dinner`;
}
},
},
// Destination routes
{path: 'restaurant/:location/menu/breakfast', component: Menu},
{path: 'restaurant/:location/menu/lunch', component: Menu},
{path: 'restaurant/:location/menu/dinner', component: Menu},
// Default redirect
{path: '', redirectTo: '/restaurant/downtown/menu', pathMatch: 'full'},
];
如需了解更多,請參閱 RedirectFunction 的 API 文件。
使用 RedirectCommand 從元件與資源重新導向
除了靜態與函式式路由重新導向之外,元件與路由資源也可以透過擲出 RedirectCommand,以命令式的方式觸發重新導向。這在重新導向未驗證的使用者,或是在擷取資料期間處理動態授權檢查時特別有用:
import {Component, inject, resource} from '@angular/core';
import {Router, RedirectCommand} from '@angular/router';
@Component({
selector: 'app-account',
template: `<p>Account Details</p>`,
})
export class AccountPage {
private router = inject(Router);
accountData = resource({
loader: async () => {
const response = await fetch('/api/account');
if (response.status === 401) {
// Automatically redirects to /login when unauthorized
throw new RedirectCommand(this.router.parseUrl('/login'));
}
return response.json();
},
});
}
當 RedirectCommand 在路由元件的建構函式、生命週期鉤子或路由資源載入器中被擲出時,Angular 路由器會攔截這個指令,並自動將導覽派送到目標 URL。
後續步驟
如需關於 redirectTo 屬性的更多資訊,請參閱 API 文件。
如需進一步了解錯誤邊界與攔截元件失敗,請參閱錯誤邊界指南。