Route 起步

2020-07-07 16:16 更新

開始本應(yīng)用的一個簡版,它在兩個空路由之間導(dǎo)航。

用 Angular CLI 生成一個范例應(yīng)用。

  1. ng new angular-router-sample

定義路由

路由器必須用“路由定義”的列表進(jìn)行配置。

每個定義都被翻譯成了一個Route對象。該對象有一個 path 字段,表示該路由中的 URL 路徑部分,和一個 component 字段,表示與該路由相關(guān)聯(lián)的組件。

當(dāng)瀏覽器的 URL 變化時或在代碼中告訴路由器導(dǎo)航到一個路徑時,路由器就會翻出它用來保存這些路由定義的注冊表。

第一個路由執(zhí)行以下操作:

  • 當(dāng)瀏覽器地址欄的 URL 變化時,如果它匹配上了路徑部分 "/crisis-center",路由器就會激活一個 CrisisListComponent 的實例,并顯示它的視圖。

  • 當(dāng)應(yīng)用程序請求導(dǎo)航到路徑 "/crisis-center" 時,路由器激活一個 CrisisListComponent 的實例,顯示它的視圖,并將該路徑更新到瀏覽器地址欄和歷史。

第一個配置定義了由兩個路由構(gòu)成的數(shù)組,它們用最短路徑指向了 CrisisListComponentHeroListComponent。

生成 CrisisListHeroList 組件,以便路由器能夠渲染它們。

  1. ng generate component crisis-list

  1. ng generate component hero-list

  1. Path:"src/app/crisis-list/crisis-list.component.html" 。

  1. <h2>CRISIS CENTER</h2>
  2. <p>Get your crisis here</p>

  1. Path:"src/app/hero-list/hero-list.component.html" 。

  1. <h2>HEROES</h2>
  2. <p>Get your heroes here</p>

注冊 Router 和 Routes

為了使用 Router,你必須注冊來自 @angular/router 包中的 RouterModule。定義一個路由數(shù)組 appRoutes,并把它傳給 RouterModule.forRoot() 方法。RouterModule.forRoot() 方法會返回一個模塊,其中包含配置好的 Router 服務(wù)提供者,以及路由庫所需的其它提供者。一旦啟動了應(yīng)用,Router 就會根據(jù)當(dāng)前的瀏覽器 URL 進(jìn)行首次導(dǎo)航。

注:

  • RouterModule.forRoot() 方法是用于注冊全應(yīng)用級提供者的編碼模式。要詳細(xì)了解全應(yīng)用級提供者。

Path:"src/app/app.module.ts (first-config)" 。

  1. import { NgModule } from '@angular/core';
  2. import { BrowserModule } from '@angular/platform-browser';
  3. import { FormsModule } from '@angular/forms';
  4. import { RouterModule, Routes } from '@angular/router';
  5. import { AppComponent } from './app.component';
  6. import { CrisisListComponent } from './crisis-list/crisis-list.component';
  7. import { HeroListComponent } from './hero-list/hero-list.component';
  8. const appRoutes: Routes = [
  9. { path: 'crisis-center', component: CrisisListComponent },
  10. { path: 'heroes', component: HeroListComponent },
  11. ];
  12. @NgModule({
  13. imports: [
  14. BrowserModule,
  15. FormsModule,
  16. RouterModule.forRoot(
  17. appRoutes,
  18. { enableTracing: true } // <-- debugging purposes only
  19. )
  20. ],
  21. declarations: [
  22. AppComponent,
  23. HeroListComponent,
  24. CrisisListComponent,
  25. ],
  26. bootstrap: [ AppComponent ]
  27. })
  28. export class AppModule { }

對于最小化的路由配置,把配置好的 RouterModule 添加到 AppModule 中就足夠了。但是,隨著應(yīng)用的成長,你將需要將路由配置重構(gòu)到單獨(dú)的文件中,并創(chuàng)建路由模塊,路由模塊是一種特殊的、專做路由的服務(wù)模塊。

RouterModule.forRoot() 注冊到 AppModuleimports 數(shù)組中,能讓該 Router 服務(wù)在應(yīng)用的任何地方都能使用。

添加路由出口

根組件 AppComponent 是本應(yīng)用的殼。它在頂部有一個標(biāo)題、一個帶兩個鏈接的導(dǎo)航條,在底部有一個路由器出口,路由器會在它所指定的位置上渲染各個組件。

路由出口扮演一個占位符的角色,表示路由組件將會渲染到哪里。

該組件所對應(yīng)的模板是這樣的:

Path:"src/app/app.component.html" 。

  1. <h1>Angular Router</h1>
  2. <nav>
  3. <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
  4. <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
  5. </nav>
  6. <router-outlet></router-outlet>

定義通配符路由

你以前在應(yīng)用中創(chuàng)建過兩個路由,一個是 "/crisis-center",另一個是 "/heroes"。 所有其它 URL 都會導(dǎo)致路由器拋出錯誤,并讓應(yīng)用崩潰。

可以添加一個通配符路由來攔截所有無效的 URL,并優(yōu)雅的處理它們。 通配符路由的 path 是兩個星號(**),它會匹配任何 URL。 而當(dāng)路由器匹配不上以前定義的那些路由時,它就會選擇這個通配符路由。 通配符路由可以導(dǎo)航到自定義的“404 Not Found”組件,也可以重定向到一個現(xiàn)有路由。

路由器會使用先到先得的策略來選擇路由。 由于通配符路由是最不具體的那個,因此務(wù)必確保它是路由配置中的最后一個路由。

要測試本特性,請往 HeroListComponent 的模板中添加一個帶 RouterLink 的按鈕,并且把它的鏈接設(shè)置為一個不存在的路由 "/sidekicks"。

Path:"src/app/hero-list/hero-list.component.html (excerpt)" 。

  1. <h2>HEROES</h2>
  2. <p>Get your heroes here</p>
  3. <button routerLink="/sidekicks">Go to sidekicks</button>

當(dāng)用戶點(diǎn)擊該按鈕時,應(yīng)用就會失敗,因為你尚未定義過 "/sidekicks" 路由。

不要添加 "/sidekicks" 路由,而是定義一個“通配符”路由,讓它導(dǎo)航到 PageNotFoundComponent 組件。

Path:"src/app/app.module.ts (wildcard)" 。

  1. { path: '**', component: PageNotFoundComponent }

創(chuàng)建 PageNotFoundComponent,以便在用戶訪問無效網(wǎng)址時顯示它。

  1. ng generate component page-not-found

Path:"src/app/page-not-found.component.html (404 component)" 。

  1. <h2>Page not found</h2>

現(xiàn)在,當(dāng)用戶訪問 "/sidekicks" 或任何無效的 URL 時,瀏覽器就會顯示 “Page not found” 。 瀏覽器的地址欄仍指向無效的 URL

設(shè)置跳轉(zhuǎn)

應(yīng)用啟動時,瀏覽器地址欄中的初始 URL 默認(rèn)是這樣的:

  1. localhost:4200

它不能匹配上任何硬編碼進(jìn)來的路由,于是就會走到通配符路由中去,并且顯示 PageNotFoundComponent

這個應(yīng)用需要一個有效的默認(rèn)路由,在這里應(yīng)該用英雄列表作為默認(rèn)頁。當(dāng)用戶點(diǎn)擊 "Heroes" 鏈接或把 "localhost:4200/heroes" 粘貼到地址欄時,它應(yīng)該導(dǎo)航到列表頁。

添加一個 redirect 路由,把最初的相對 URL('')轉(zhuǎn)換成所需的默認(rèn)路徑(/heroes)。

在通配符路由上方添加一個默認(rèn)路由。 在下方的代碼片段中,它出現(xiàn)在通配符路由的緊上方,展示了這個里程碑的完整 appRoutes

Path:"src/app/app-routing.module.ts (appRoutes)" 。

  1. const appRoutes: Routes = [
  2. { path: 'crisis-center', component: CrisisListComponent },
  3. { path: 'heroes', component: HeroListComponent },
  4. { path: '', redirectTo: '/heroes', pathMatch: 'full' },
  5. { path: '**', component: PageNotFoundComponent }
  6. ];

瀏覽器的地址欄會顯示 ".../heroes",好像你直接在那里導(dǎo)航一樣。

重定向路由需要一個 pathMatch 屬性,來告訴路由器如何用 URL 去匹配路由的路徑。 在本應(yīng)用中,路由器應(yīng)該只有在*完整的 URL_等于 '' 時才選擇 HeroListComponent 組件,因此要把 pathMatch 設(shè)置為 'full'。

聚焦 PATHMATCH

從技術(shù)角度看,pathMatch = 'full' 會導(dǎo)致 URL 中剩下的、未匹配的部分必須等于 ''。 在這個例子中,跳轉(zhuǎn)路由在一個頂層路由中,因此剩下的_URL和完整的_URL是一樣的。

pathMatch 的另一個可能的值是 'prefix',它會告訴路由器:當(dāng)*剩下的_URL以這個跳轉(zhuǎn)路由中的 prefix 值開頭時,就會匹配上這個跳轉(zhuǎn)路由。 但這不適用于此示例應(yīng)用,因為如果 pathMatch 值是 'prefix',那么每個 URL 都會匹配 ''。

嘗試把它設(shè)置為 'prefix',并點(diǎn)擊Go to sidekicks按鈕。這是因為它是一個無效 URL,本應(yīng)顯示“Page not found” 頁。 但是,你仍然在“英雄列表”頁中。在地址欄中輸入一個無效的 URL,你又被路由到了 /heroes。 每一個 URL,無論有效與否,都會匹配上這個路由定義。

默認(rèn)路由應(yīng)該只有在整個URL 等于 '' 時才重定向到 HeroListComponent,別忘了把重定向路由設(shè)置為 pathMatch = 'full'

小結(jié)

當(dāng)用戶單擊某個鏈接時,該示例應(yīng)用可以在兩個視圖之間切換。

本節(jié)涵蓋了以下幾點(diǎn)的做法:

  • 加載路由庫。

  • 往殼組件的模板中添加一個導(dǎo)航條,導(dǎo)航條中有一些 A 標(biāo)簽、routerLink 指令和 routerLinkActive 指令。

  • 往殼組件的模板中添加一個 router-outlet 指令,視圖將會被顯示在那里。

  • RouterModule.forRoot() 配置路由器模塊。

  • 設(shè)置路由器,使其合成 HTML5 模式的瀏覽器 URL。

  • 使用通配符路由來處理無效路由。

  • 當(dāng)應(yīng)用在空路徑下啟動時,導(dǎo)航到默認(rèn)路由。

初學(xué)者應(yīng)用結(jié)構(gòu)圖:

本節(jié)產(chǎn)生的文件列表:

  1. Path:"app.component.html" 。

  1. <h1>Angular Router</h1>
  2. <nav>
  3. <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
  4. <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
  5. </nav>
  6. <router-outlet></router-outlet>

  1. Path:"app.module.ts" 。

  1. import { NgModule } from '@angular/core';
  2. import { BrowserModule } from '@angular/platform-browser';
  3. import { FormsModule } from '@angular/forms';
  4. import { RouterModule, Routes } from '@angular/router';
  5. import { AppComponent } from './app.component';
  6. import { CrisisListComponent } from './crisis-list/crisis-list.component';
  7. import { HeroListComponent } from './hero-list/hero-list.component';
  8. import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
  9. const appRoutes: Routes = [
  10. { path: 'crisis-center', component: CrisisListComponent },
  11. { path: 'heroes', component: HeroListComponent },
  12. { path: '', redirectTo: '/heroes', pathMatch: 'full' },
  13. { path: '**', component: PageNotFoundComponent }
  14. ];
  15. @NgModule({
  16. imports: [
  17. BrowserModule,
  18. FormsModule,
  19. RouterModule.forRoot(
  20. appRoutes,
  21. { enableTracing: true } // <-- debugging purposes only
  22. )
  23. ],
  24. declarations: [
  25. AppComponent,
  26. HeroListComponent,
  27. CrisisListComponent,
  28. PageNotFoundComponent
  29. ],
  30. bootstrap: [ AppComponent ]
  31. })
  32. export class AppModule { }

  1. Path:"hero-list/hero-list.component.html" 。

  1. <h2>HEROES</h2>
  2. <p>Get your heroes here</p>
  3. <button routerLink="/sidekicks">Go to sidekicks</button>

  1. Path:"crisis-list/crisis-list.component.html" 。

  1. <h2>CRISIS CENTER</h2>
  2. <p>Get your crisis here</p>

  1. Path:"page-not-found/page-not-found.component.html" 。

  1. <h2>Page not found</h2>

  1. Path:"index.html" 。

  1. <html lang="en">
  2. <head>
  3. <!-- Set the base href -->
  4. <base href="/">
  5. <title>Angular Router</title>
  6. <meta charset="UTF-8">
  7. <meta name="viewport" content="width=device-width, initial-scale=1">
  8. </head>
  9. <body>
  10. <app-root></app-root>
  11. </body>
  12. </html>
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號