2017-03-06 941 views
2

因此,我試圖通過使用警衛來保護對幾條路線的訪問。我使用以下途徑可以這樣做:試圖瞭解CanActivate和CanActivateChild之間的區別

const adminRoutes : Routes = [ 
    { 
    path: 'admin', 
    component: AdminComponent, 
    canActivate: [ AuthGuardService ], 
    children : [ 
     { 
     path: '', 
     canActivateChild: [ AuthGuardService ], 
     children: [ 
      { path: 'edit', component: DashboardComponent}, 
      { path: '', component: DashboardComponent} 
     ] 
     } 
    ] 
    } 
]; 

下面就來看看在什麼AuthGuardService看起來像

import { Injectable } from '@angular/core'; 
import {CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router"; 

@Injectable() 
export class AuthGuardService implements CanActivate{ 

    constructor(private router: Router) { } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){ 
    console.log("Guarding..."); 
    return this.sessionValid(); 
    } 

    canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){ 
    console.log("Guarding children..."); 
    return this.canActivate(route, state); 
    } 

    sessionValid() : boolean { 
    //tests 
    } 

} 

當我嘗試進入「/管理員」和「/管理/編輯」只有canActivatecanActivateChild被註釋掉)的控制檯顯示

Guarding... 

當我刪除canActivate,並把canActivateChild回控制檯DISPLA ys

Guarding children... 

當我保持這兩者時,它會返回到顯示Guarding...。 所以,我的問題是canActivate保護根元素和孩子時,有什麼目的canActivateChild

PS:我知道canActivateChild在孩子路線被激活之前運行。但是,這有什麼好處?是不是隻保留其中一個足夠?

回答

6

兩者都很重要,因爲您可能有不同的要求,即用戶可以到達根組件但不滿足子組件的條件。

示例:您可能遇到以下情況:用戶必須通過身份驗證才能導航到根組件,但必須具有權限「x」才能訪問子組件。在這種情況下,canActivateChild可以節省大量打字,因爲必須爲每個孩子添加canActivate警衛。

編輯:

例如,你可能有一個管理模塊,所有路由都需要防止未經授權的進入加以防護:

{ 
    path: 'admin', 
    component: AdminComponent, 
    canActivate: [ AuthGuardService ], 
    children : [ 
     { 
     path: '', component: ..., 
     }, 
     { 
     path: 'manage-users', component: ..., 
     }, 
     { 
     path: 'manage-roles', component: ..., 
     } 
    ] 
    } 

這將需要保護的從上而下。沒有未經授權的訪問任何路線,包括根和兒童。在這種情況下,canActivate在根本上很好地保護了一切。

但你也可能有,你有一個功能模塊,其中只有某些孩子需要加以防護時間:

{ 
    path: 'featureA', 
    component: ..., 
    canActivateChild: [ AuthGuardService ], 
    children : [ 
     { 
     path: 'manage-feature', component: ..., 
     }, 
     { 
     path: 'manage-members', component: ..., 
     } 
    ], 
    {path: 'featureB', component: ...} 
    } 

在這種情況下,也許所有用戶都需要正本清源組件的featureA「和'featureB',但只有某些用戶需要能夠導航到'featureA'的子路由。在這種情況下,在根級別使用一名警衛人員更容易保護兒童,但不是根本身。另一種方法是在每條兒童路線上放置canActivate警衛,這可能會很乏味。

這一切都取決於您的要求,但它可以很好同時具有canActivatecanActivateChild的選項。

+0

我們不能只使用canActivate而不是canActivateChild嗎? – YounesM

+2

也許,這取決於您的要求。我上面給出的例子可能有點太過於人爲設計。 'canActivateChild'在每個子路由被激活之前運行。你確實可以使用'canActivate'來保護一個所有孩子的根組件,但是你可能有孩子,某些用戶不需要查看他們何時需要能夠看到根組件。例如,您可以將一些管理組件中的數據添加到大多數或所有用戶需要到達根目錄的Feature模塊中,但不一定是某些路由的子模塊。 –

0

以我認爲,CanActivate用來限制從特定路徑的訪問和所有的子路徑和CanActivateChild被用來限制CanActivate路徑內部訪問一個特定的組。

例子:

{ 
    path: 'admin', 
    component: AdminComponent, 
    canActivate: [AuthGuardService], 
    children : [ 
    { 
     path: 'books', component: ..., 
    }, 
    { 
     path: 'authors', component: ..., 
    }, 
    { 
     path: 'payments', 
     canActivateChild: [AuthGuardService], 
     children: [ 
     { 
      path: 'list', component: ... 
     }, 
     { 
      path: 'list/:id', component: ... 
     } 
     ] 
    } 
    ] 
} 

因爲你需要兩種類型的驗證,你不能有兩個canActivate方法,所以你需要canActivateChild用於檢查canActivate路內的permision。顯然,你可以創建一個不同的警衛服務(AuthGuardForChildrenRoutes),仍然使用canActivate方法,但那不是重點。