什麼是Routing?
Routing意指路由器,也就是由一個路由器來決定現在要顯示的頁面是什麼
在套用Routing時,會有下列的實踐流程
1. 套用轉址設定(讓伺服器不去真正網址所在的位置去讀取資料,而改由Routing來決定現在要顯示什麼畫面)
2. 由url分析要顯示的狀態是什麼
3. 由狀態去獲得真正要取得那些資訊
4. 從這些資訊組成實體
5. 套用導覽動作,由這個畫面切換至另一個畫面
在Angular裡,最佳做法是將載入和設定Routing放在一個top-level的模組內,並於AppModule內來import所有的路由資訊。
按照慣例,模組AppRoutingModule
和app-routing.module.ts
會放在src/app
裡
Angular的Routing 產生的虛擬 URL,並不是真的存在於檔案系統裡,因此需要伺服器能夠支援,否則重新整理時會出現404 not found。
新增AppRoutingModule
透過下列CLI的指令來新增一個Routing
ng generate module app-routing --flat --module=app
--flat
的意思是將產出文件放在src/app裡,而非自己一個資料夾
--module=app
則是告知CLI註冊這個Routing在AppModule的imports裡
新產生的src/app/app-routing.module.ts檔案內容如下:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [] }) export class AppRoutingModule { }
一般我們不會在Routing裡宣告元件,因此可以將@NgModule.declarations及CommonModule的宣告刪除
通常我們會使用Routes與RouterModule來實做Routing,修改後的檔案如下:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @NgModule({ exports: [ RouterModule ] }) export class AppRoutingModule {}
增加Routes
此時我們來設定不同路徑要導向的位置,如下面的程式碼
import { HeroesComponent } from './heroes/heroes.component'; const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'heroes', component: HeroesComponent }, { path: 'detail/:id', component: HeroDetailComponent } ];
上述程式碼代表在網址為http://localhost/heroes時,會在標籤內顯示HeroesComponent這元件的內容。
另外,也要設定當伺服器剛運行時(http://localhost/),要顯示的模組。
設定完Router的map後,將之設定進RouterModule.forRoot()裡
然後再將這整個Router功能設定為可以被export,之後便可以在app.module裡import這個Router
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { DashboardComponent } from './dashboard/dashboard.component'; import { HeroesComponent } from './heroes/heroes.component'; import { HeroDetailComponent } from './hero-detail/hero-detail.component'; const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'dashboard', component: DashboardComponent }, { path: 'detail/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroesComponent } ]; @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule {}
而detail/:id裡的:id可於HeroDetailComponent裡去取得,來做進一步更詳細的資料顯示
取得方法如下:
ngOnInit(): void { this.getHero(); } getHero(): void { const id = +this.route.snapshot.paramMap.get('id');//用route.snapshot.paramMap.get取得Routing時傳入的變數 this.heroService.getHero(id) .subscribe(hero => this.hero = hero); }
我們可以發現,例子中不同的path為所傳入的參數不同,它們代表不同的意義,可以更多元化的設定Routing的功能。Routes可傳入的參數有下面這些
interface Route { path?: string //瀏覽器上方的網址列的字串 pathMatch?: string //當導航至此網址時要顯示的元件 matcher?: UrlMatcher //網址列過濾器 component?: Type<any> redirectTo?: string //要轉址到那邊 outlet?: string canActivate?: any[] canActivateChild?: any[] canDeactivate?: any[] canLoad?: any[] data?: Data //要傳入元件裡的資料 resolve?: ResolveData children?: Routes loadChildren?: LoadChildren runGuardsAndResolvers?: RunGuardsAndResolvers }
在這邊可看一下APP_BASE_HREF的設定方式
如果沒有設定,會跑出錯誤訊息如下:
另一個簡單的方式則是在index.html增加下面這行,也可以解決這個錯誤
<base href="/">
在src/app/app.component.html中增加這個導航功能
<h1>{{title}}</h1> <router-outlet></router-outlet>
利用routerLink來增加導航用超連結
修改src/app/app.component.html如下:
<h1>{{title}}</h1> <nav> <a routerLink="/heroes">Heroes</a> </nav> <router-outlet></router-outlet>
如果要回上一頁則使用
goBack(): void { this.location.back(); }
這篇文章的範例檔案可由此觀看: live example / download example。