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,會屏蔽 AppModule 的 Router,有就是說 Router 將不再整個 app 共用,而是各 module 有自己的 Router,因此 RouterModule 特別不提供 provider,而是改由 forRoot() 與 forChild() 提供,如此整個 app 將只會有一份 Router

route001

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

理論上 app.module.ts 與 app-routing.module.ts 可以合一,但因為 app.module.ts 有他原本的職責,如 declarations、imports 、 providers 與 bootstrap,且簡單的 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.ts 與 app-routing.module.ts 兩個檔案
  3. 在 AppModule 中,會自動幫我們 import AppRoutingModule

刪除 app.module.ts

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

因為我們目的是要 Angular CLI 幫我們建立 app-routing.module.ts,app.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 的方式建立 LoginComponent 與 PostComponent (略)

設定 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>

當在 AppRoutingModule 的 routes 設定 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

▲