Angular 已經內建 Route,可直接使用

傳統以後端為主的 MVC 寫法,route 會寫在後端;前後端分離的 SPA 寫法,前後端有各自的 route,前端的 route 負責切換 component,而後端的 route 則負責 API。

Version


macOS High Sierra 10.13.3
Node.js 8.9.4
Angular CLI 1.6.7
Angular 5.2.4

建立 Route


建立專案時一併建立 Route

1
$ ng new MyProject --routing

新建專案時,加上 --routing 參數。

route000

  1. Angular CLI 會替我們在 src/app 目錄下新增 app-routing.module.ts 檔案
  2. class 名稱為 AppRoutingModule
  3. routes 陣列即位自訂 route 之處

第 7 行

1
imports: [RouterModule.forRoot(routes)],

一般來說,imports 要的都是單純 module,如 BrowserModule,但這裡用的卻是 RouterModule.forRoot()

  • forRoot()RouterModule 的 factory method,為 static, 傳入 routes 後,回傳給 AppModule 所使用的 RouterModule
  • forChild() 亦為 RouterModule 的 factory method,為 static,傳入 routes 後,回傳其他 module 所使用的 RouterModule

之所以要特別用 forRoot()forChild(),因為當 AppModule 與其他 module 都 import RouterModule 時,由於其他 module 都有自己的 DI injector,會屏蔽 AppModuleRouter,有就是說 Router 將不再整個 app 共用,而是各 module 有自己的 Router,因此 RouterModule 特別不提供 provider,而是改由 forRoot()forChild() 提供,如此整個 app 將只會有一份 Router

route001

  1. Angular CLI 還替我們修改了 app.module.ts
  2. 自動將 AppRoutingModule import 進來

理論上 app.module.tsapp-routing.module.ts 可以合一,但因為 app.module.ts 有他原本的職責,如 declarationsimportsprovidersbootstrap,且簡單的 app 也可能也沒使用 route,因此特別將 route 部分特別獨立為 app-routing.module.ts,再 import 進 app.module.ts 即可

建立專案後事後加上 Route

假如一開始建立專案時沒加上 --routing ,也可事後再建立 route。

Angular CLI 並沒有提供單獨建立 route 的指令,只能在建立 module 時,順便加上 --routing 參數建立 route

將 app.module.ts 暫時改名

route002

  1. app.module.ts 暫時改名為 app.module.ts.bak

因為我們即將重建 app.module.ts,所以先將目前的 app.module.ts 改名避開

重新建立有 Route 的 AppModule

1
~/MyProject $ ng g m App --flat --routing

m : module 的縮寫

--flat : 不要將 AppRouting 建立在目前目錄下,而是建立在 src/app 目錄下

--routing : 一併建立 AppRoutingModule

route003

  1. 在專案目錄下執行 ng g m App --flat —routing
  2. Angular CLI 會替我們建立 app.module.tsapp-routing.module.ts 兩個檔案
  3. AppModule 中,會自動幫我們 import AppRoutingModule

刪除 app.module.ts

Angular CLI 剛剛幫我們建立了全新的 app.module.ts,手動將此檔刪除

因為我們目的是要 Angular CLI 幫我們建立 app-routing.module.tsapp.module.ts 沒有利用價值需刪除

將 app.module.ts.bak 改為 app.module.ts

route004

  1. app.module.ts 刪除,再將 app.module.ts.bak 重新命名為 app.module.ts

app.module.ts.bak 才是我們原本的 app.module.ts

修改 AppModule

route005

  1. 選擇 app.module.ts
  2. imports 加上剛剛建立的 AppRoutingModule

修改 AppRoutingModule

route006

  1. 選擇 app-routing.module.ts
  2. forChild() 改成 forRoot()

    如此無論是一開始建立專案就加上 --routing 參數,或者先建立專案,事後再補建立 route,目前 AppModule 都有相同的 AppRoutingModule

設定 Route

建立 Login 與 Post Component

使用一般建立 component 的方式建立 LoginComponentPostComponent (略)

設定 routes

app-routing.module.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { NgModule, Component } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { PostComponent } from './post/post.component';

const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'post', component: PostComponent },
{ path: '', redirectTo: '', pathMatch: 'full'}
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

第 6 行

1
2
3
4
5
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'post', component: PostComponent },
{ path: '', redirectTo: '', pathMatch: 'full'}
];

Routes 為 Angular 定義的 Route 陣列,用來設定 user 自己的 route 定義。

第 7 行

1
{ path: 'login', component: LoginComponent },
  • path : 設定 route 路徑
  • component : 當符合 path 定義時,該顯示的 component

當 URI 為 login 時,顯示 LoginComponent

第 8 行

1
{ path: 'post', component: PostComponent },

當 URI 為 post 時,顯示 PostComponent

第 9 行

1
{ path: '', redirectTo: '', pathMatch: 'full' },
  • redirectTo : redirect 到其他 URI 路徑
  • pathMatch : 與 path 的匹配方式

當 URI 為 空字串,redirect 到 '',且必須完全符合 path 定義

app.component.html

1
2
3
4
5
6
Welcome to {{ title }}!
<p></p>
<button routerLink="login">Login</button>
<button routerLink="post">Post</button>
<button routerLink="">Home</button>
<router-outlet></router-outlet>

第 6 行

1
<router-outlet></router-outlet>

當在 AppRoutingModuleroutes 設定 component 時,會顯示在哪呢 ? 就是顯示在 HTML template 的 <router-outlet></router-outlet> 內。

第 2 行

1
<a routerLink="login">Login</a>

原本的 <a> 會使用 href,但這會導致 Angular 使用後端的 route,也就是整個網頁會重新載入;若使用 routerLink,則 Angular 會使用前端的 route,也就是將 <router-outlet></router-outlet> 換成其他 component,使用者體驗較好。

Conclusion


  • Angular 也有自己的 route,傳統頁面跳轉的 route 必須改設定在 Angular

Sample Code


完整的範例可以在 GitHub 上找到

2018-02-13