路由與導航
在用戶使用應用程序時,Angular 的路由器能讓用戶從一個視圖導航到另一個視圖。
導入路由
Angular 的路由器是一個可選的服務畸肆,它用來呈現(xiàn)指定的 URL 所對應的視圖。 它并不是 Angular 核心庫的一部分宙址,而是在它自己的 @angular/router 包中轴脐。 像其它 Angular 包一樣,你可以從它導入所需的一切抡砂。
import { RouterModule, Routes } from '@angular/router';
配置路由
每個帶路由的 Angular 應用都有一個Router(路由器)服務的單例對象大咱。 當瀏覽器的 URL 變化時,路由器會查找對應的 Route(路由)注益,并據(jù)此決定該顯示哪個組件碴巾。
路由器需要先配置才會有路由信息。 下面的例子創(chuàng)建了五個路由定義丑搔,并用 RouterModule.forRoot() 方法來配置路由器厦瓢, 并把它的返回值添加到 AppModule
的 imports
數(shù)組中。
const appRoutes: Routes = [
{ path: 'crisis-center', component: CrisisListComponent },
{ path: 'hero/:id', component: HeroDetailComponent },
{
path: 'heroes',
component: HeroListComponent,
data: { title: 'Heroes List' }
},
{ path: '',
redirectTo: '/heroes',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // 打印所有路由事件
)
],
...
})
export class AppModule { }
這里的路由數(shù)組 appRoutes
描述如何進行導航啤月。 把它傳給 RouterModule.forRoot() 方法并傳給本模塊的 imports
數(shù)組就可以配置路由器煮仇。
每個 Route 都會把一個 URL 的 path
映射到一個組件。 注意谎仲,path
不能以斜杠(/
)開頭浙垫。 路由器會為解析和構建最終的 URL,這樣當你在應用的多個視圖之間導航時郑诺,可以任意使用相對路徑和絕對路徑绞呈。
第二個路由中的 :id
是一個路由參數(shù)的令牌(Token)。比如 /hero/42
這個 URL 中间景,“42”就是 id
參數(shù)的值。 此 URL 對應的 HeroDetailComponent
組件將據(jù)此查找和展現(xiàn) id
為 42 的英雄艺智。 在本章中稍后的部分倘要,你將會學習關于路由參數(shù)的更多知識。
第三個路由中的 data
屬性用來存放于每個具體路由有關的任意信息。該數(shù)據(jù)可以被任何一個激活路由訪問封拧,并能用來保存諸如 頁標題志鹃、面包屑以及其它靜態(tài)只讀數(shù)據(jù)。本章稍后的部分泽西,你將使用resolve 守衛(wèi)來獲取動態(tài)數(shù)據(jù)曹铃。
第四個路由中的空路徑(''
)表示應用的默認路徑,當 URL 為空時就會訪問那里捧杉,因此它通常會作為起點陕见。 這個默認路由會重定向到 URL /heroes
,并顯示 HeroesListComponent
味抖。
最后一個路由中的 **
路徑是一個通配符评甜。當所請求的 URL 不匹配前面定義的路由表中的任何路徑時,路由器就會選擇此路由仔涩。 這個特性可用于顯示“404 - Not Found”頁忍坷,或自動重定向到其它路由。
這些路由的定義順序是刻意如此設計的熔脂。路由器使用先匹配者優(yōu)先的策略來匹配路由佩研,所以,具體路由應該放在通用路由的前面霞揉。在上面的配置中旬薯,帶靜態(tài)路徑的路由被放在了前面,后面是空路徑路由零聚,因此它會作為默認路由袍暴。而通配符路由被放在最后面,這是因為它能匹配上每一個 URL隶症,因此應該只有在前面找不到其它能匹配的路由時才匹配它政模。
如果你想要看到在導航的生命周期中發(fā)生過哪些事件,可以使用路由器默認配置中的 enableTracing 選項蚂会。它會把每個導航生命周期中的事件輸出到瀏覽器的控制臺淋样。 這應該只用于調試。你只需要把 enableTracing: true 選項作為第二個參數(shù)傳給 RouterModule.forRoot() 方法就可以了胁住。
路由出口
RouterOutlet 是一個來自路由模塊中的指令趁猴,它的用法類似于組件。 它扮演一個占位符的角色彪见,用于在模板中標出一個位置儡司,路由器將會把要顯示在這個出口處的組件顯示在這里。
<router-outlet></router-outlet>
路由器鏈接
現(xiàn)在余指,你已經(jīng)有了配置好的一些路由捕犬,還找到了渲染它們的地方,但又該如何導航到它呢?固然碉碉,從瀏覽器的地址欄直接輸入 URL 也能做到贴届,但是大多數(shù)情況下蜡吧,導航是某些用戶操作的結果毫蚓,比如點擊一個 A 標簽。
考慮下列模板:
<h1>Angular Router</h1>
<nav>
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet>
a 標簽上的 RouterLink 指令讓路由器得以控制這個 a 元素斩跌。 這里的導航路徑是固定的绍些,因此可以把一個字符串賦給 routerLink(“一次性”綁定)。
如果需要更加動態(tài)的導航路徑耀鸦,那就把它綁定到一個返回鏈接參數(shù)數(shù)組的模板表達式柬批。 路由器會把這個數(shù)組解析成完整的 URL。
路由鏈接的激活狀態(tài)
RouterLinkActive 指令會基于當前的 RouterState為活動的 RouterLink 切換所綁定的 css 類。
在每個 A 標簽上洛姑,你會看到一個到 RouterLinkActive 的屬性綁定上沐,形如 routerLinkActive="..."。
等號右邊的模板表達式包含一些用空格分隔的 CSS 類名楞艾,當這個鏈接激活時参咙,路由器將會把它們加上去(并在處于非活動狀態(tài)時移除)。你還可以把 RouterLinkActive 設置為一個類組成的字符串两入,如 [routerLinkActive]="'active fluffy'"净宵,或把它綁定到一個返回類似字符串的組件屬性。
路由鏈接的激活狀態(tài)會向下級聯(lián)到路由樹中的每個層級裹纳,所以择葡,父子路由鏈接可能會同時激活。要覆蓋這種行為剃氧,可以把 [routerLinkActiveOptions] 綁定為 { exact: true }
表達式敏储,這樣 RouterLink只有當 URL 與當前 URL 精確匹配時才會激活。
路由器狀態(tài)
在導航時的每個生命周期成功完成時朋鞍,路由器會構建出一個 ActivatedRoute組成的樹已添,它表示路由器的當前狀態(tài)迫横。 你可以在應用中的任何地方用 Router 服務及其 routerState屬性來訪問當前的 RouterState 值。
RouterState
中的每個 ActivatedRoute
都提供了從任意激活路由開始向上或向下遍歷路由樹的一種方式酝碳,以獲得關于父、子恨狈、兄弟路由的信息疏哗。
路由信息獲取
該路由的路徑和參數(shù)可以通過注入進來的一個名叫ActivatedRoute的路由服務來獲取。 它有一大堆有用的信息禾怠,包括:
屬性 | 說明 |
---|---|
url | 路由路徑的 Observable 對象返奉,是一個由路由路徑中的各個部分組成的字符串數(shù)組。 |
data | 一個 Observable 吗氏,其中包含提供給路由的 data 對象芽偏。也包含由解析守衛(wèi)(resolve guard)解析而來的值。 |
paramMap | 一個 Observable 弦讽,其中包含一個由當前路由的必要參數(shù)和可選參數(shù)組成的map對象污尉。用這個 map 可以獲取來自同名參數(shù)的單一值或多重值。 |
queryParamMap | 一個 Observable 往产,其中包含一個對所有路由都有效的查詢參數(shù)組成的map對象被碗。 用這個 map 可以獲取來自查詢參數(shù)的單一值或多重值。 |
fragment | 一個適用于所有路由的 URL 的 fragment(片段)的 Observable 仿村。 |
outlet | 要把該路由渲染到的 RouterOutlet 的名字锐朴。對于無名路由,它的路由名是 primary 蔼囊,而不是空串焚志。 |
routeConfig | 用于該路由的路由配置信息,其中包含原始路徑畏鼓。 |
parent | 當該路由是一個子路由時酱酬,表示該路由的父級 ActivatedRoute。 |
firstChild | 包含該路由的子路由列表中的第一個 ActivatedRoute滴肿。 |
children | 包含當前路由下所有已激活的子路由岳悟。 |
有兩個舊式屬性仍然是有效的,但它們不如其替代品那樣強力泼差,建議不再用它們贵少,它們還將在未來的 Angular 版本中廢棄
params
—— 一個Observable
對象,其中包含當前路由的必要參數(shù)和可選參數(shù)堆缘。請改用paramMap
queryParams
—— 一個Observable
對象滔灶,其中包含對所有路由都有效的查詢參數(shù)。請改用queryParamMap
路由事件
在每次導航中吼肥,Router 都會通過 Router.events 屬性發(fā)布一些導航事件录平。這些事件的范圍涵蓋了從開始導航到結束導航之間的很多時間點麻车。下表中列出了全部導航事件:
路由器事件 | 說明 |
---|---|
NavigationStart | 本事件會在導航開始時觸發(fā)。 |
RouteConfigLoadStart | 本事件會在 Router惰性加載 某個路由配置之前觸發(fā)斗这。 |
RouteConfigLoadEnd | 本事件會在惰性加載了某個路由后觸發(fā)动猬。 |
RoutesRecognized | 本事件會在路由器解析完 URL,并識別出了相應的路由時觸發(fā) |
GuardsCheckStart | 本事件會在路由器開始 Guard 階段之前觸發(fā)表箭。 |
ChildActivationStart | 本事件會在路由器開始激活路由的子路由時觸發(fā)赁咙。 |
ActivationStart | 本事件會在路由器開始激活某個路由時觸發(fā)。 |
GuardsCheckEnd | 本事件會在路由器成功完成了 Guard 階段時觸發(fā)免钻。 |
ResolveStart | 本事件會在 Router 開始解析(Resolve)階段時觸發(fā)彼水。 |
ResolveEnd | 本事件會在路由器成功完成了路由的解析(Resolve)階段時觸發(fā)。 |
ChildActivationEnd | 本事件會在路由器激活了路由的子路由時觸發(fā)极舔。 |
ActivationEnd | 本事件會在路由器激活了某個路由時觸發(fā)凤覆。 |
NavigationEnd | 本事件會在導航成功結束之后觸發(fā)。 |
NavigationCancel | 本事件會在導航被取消之后觸發(fā)拆魏。 這可能是因為在導航期間某個路由守衛(wèi)返回了 false 盯桦。 |
NavigationError | 這個事件會在導航由于意料之外的錯誤而失敗時觸發(fā)。 |
Scroll | 本事件代表一個滾動事件稽揭。 |
總結一下
該應用有一個配置過的路由器俺附。 外殼組件中有一個 RouterOutlet,它能顯示路由器所生成的視圖溪掀。 它還有一些 RouterLink事镣,用戶可以點擊它們,來通過路由器進行導航揪胃。
下面是一些路由器中的關鍵詞匯及其含義:
路由器部件 | 含義 |
---|---|
Router(路由器) | 為激活的 URL 顯示應用組件璃哟。管理從一個組件到另一個組件的導航 |
RouterModule | 一個獨立的 NgModule,用于提供所需的服務提供商喊递,以及用來在應用視圖之間進行導航的指令随闪。 |
Routes(路由數(shù)組) | 定義了一個路由數(shù)組,每一個都會把一個 URL 路徑映射到一個組件骚勘。 |
Route(路由) | 定義路由器該如何根據(jù) URL 模式(pattern)來導航到組件铐伴。大多數(shù)路由都由路徑和組件類構成。 |
RouterOutlet(路由出口) | 該指令(<router-outlet> )用來標記出路由器該在哪里顯示視圖俏讹。 |
RouterLink(路由鏈接) | 這個指令把可點擊的 HTML 元素綁定到某個路由当宴。點擊帶有 routerLink 指令(綁定到字符串或鏈接參數(shù)數(shù)組)的元素時就會觸發(fā)一次導航。 |
RouterLinkActive(活動路由鏈接) | 當 HTML 元素上或元素內的routerLink 變?yōu)榧せ罨蚍羌せ顮顟B(tài)時泽疆,該指令為這個 HTML 元素添加或移除 CSS 類户矢。 |
ActivatedRoute(激活的路由) | 為每個路由組件提供提供的一個服務,它包含特定于路由的信息殉疼,比如路由參數(shù)梯浪、靜態(tài)數(shù)據(jù)捌年、解析數(shù)據(jù)、全局查詢參數(shù)和全局碎片(fragment)挂洛。 |
RouterState(路由器狀態(tài)) | 路由器的當前狀態(tài)包含了一棵由程序中激活的路由構成的樹礼预。它包含一些用于遍歷路由樹的快捷方法。 |
鏈接參數(shù)數(shù)組 | 這個數(shù)組會被路由器解釋成一個路由操作指南虏劲。你可以把一個RouterLink 綁定到該數(shù)組逆瑞,或者把它作為參數(shù)傳給Router.navigate 方法。 |
路由組件 | 一個帶有RouterOutlet 的 Angular 組件伙单,它根據(jù)路由器的導航來顯示相應的視圖。 |