前言

預設的情況下,任何user都是可以瀏覽到route有對應到的網址,這並不是一個好的情況。 通常會有需要一些權限的控管。

例如:

  • user是不被允許瀏覽到某個component
  • 此網址需要先登入才能使用
  • 先事先取得一些資料再顯示component
  • 在離開component之前先取得改變的資料
  • 或者在user離開之前詢問是否要不儲存離開

以上情況,都可以在route configuration新增guards達成我們要的目的。

目前共有五種guards可以使用

  • CanActivate: to mediate navigation to a route.
  • CanActivateChild: to mediate navigation to a child route.
  • CanDeactivate: to mediate navigation away from the current route.
  • Resolve: to perform route data retrieval before route activation.
  • CanLoad: to mediate navigation to a feature module loaded asynchronously.

Guard的回傳值決定router的行為

  • 回傳 true,則navigation繼續
  • 回傳 false,則navigation process stops

而今天選擇CanActivate來做說明,其他guards的做法都是類似的。

原文參考:
Guards

範例

今天的範例我們要驗證使用者輸入的網址參數(:id)是不是個數字,如果不是數字,則導向到 welcome 頁面。 router設定如下:

configuration
  • ts
1
{ path: 'detail/:id', component: DetailComponent }

我們先用 angular cli 新增一個 service component

ng g s product-guard.service

angular cli 會幫我們新增好一個service component,而且我們要做的就是

  1. implements CanActivate,實作canActivate方法
  2. 因為要取得網址的資料,所以canActivate傳入ActivatedRouteSnapshot
  3. import Router使用router做導向的動作
  4. 驗證是否為數字,是數字回傳true,不是數字導向welcome頁面,回傳false
Service Component
  • ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { CanActivate, ActivatedRouteSnapshot, Router } from '@angular/router';
import { Injectable } from '@angular/core';

@Injectable()
export class ProductGuardService implements CanActivate {

constructor(private _router: Router) { }

canActivate(route: ActivatedRouteSnapshot): boolean {

let id = +route.url[1].path;
if (isNaN(id) || id < 1) {

this._router.navigate(['/welcome']);

return false;
}

return true;
}

}

以上,我們component的程式碼就寫完了。

接下來開啟app.module

  1. import ProductGuardService
  2. provider加入 ProductGuardService
  3. router設定多傳入 canActivate : ProductGuardService
app.module
  • ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
import { ProductGuardService } from './product-guard.service';

@NgModule({
declarations: [
...
],
imports: [
...
RouterModule.forRoot([
{
path: 'detail/:id',
canActivate: [ProductGuardService],
component: DetailComponent
}...
])
],
providers: [ProductGuardService],
...
})
export class AppModule { }

加入以上程式碼後,就完成了。 這樣當網址像是數字這種非數字的id參數,則網址頁就會自動導向到welcome

參考

Guards