何時使用
- 使用者無權導航到目標元件
- 使用者得先登入認證
- 顯示目標元件前,需要先獲得某些資料
- 離開元件前,需要先儲存修改,需要詢問使用者是否放棄修改
使用方法
-
路由守衛返回一個值Observable / Promise,以控制路由器的行為:
- 返回true,導航繼續
- 返回false,導航終止
-
一般專案都會有多層路由和模組懶載入,因此在路由的每個層次上,我們都可以設定多個守衛。路由檢查順序:
- 從最深的子路由從下往上檢查CanDeactivate()和CanActivateChild()守衛。
- 自上而下檢查CanActivate()守衛。
在上面的過程中,如果模組是lazyLoad的,載入之前還會檢查CanLoad()守衛。
檢查過程中任何一個守衛返回false,其他未完成的守衛會被取消,整個導航就會被取消。
-
幾個路由守衛
守衛 功能 CanActivate 導航到某路由的情況 CanActivateChild 導航到某子路由的情況 CanDeactivate 從當前路由離開的情況 Resolve 路由啟用前獲取路由資料 CanLoad 非同步導航到某特性模組(懶載入)
CanActivate: 要求認證
一般用來管理訪問者是否有許可權訪問該特性模組或元件;
在根模組下面建立一個service資料夾,用來存放公共的service
// /src/app/service/auth-guard.service.ts
import { Injectable } from `@angular/core`;
import { CanActivate, Router } from `@angular/router`;
import { HttpClient } from `@angular/common/http`;
import { Observable } from `rxjs/Observable`;
@Injectable()
export class AuthGuardService implements CanActivate {
constructor(private router: Router, private http: HttpClient) {}
canActivate(): Observable<any> {
console.log(`canActivate goes here`);
// 這裡返回一個Observable<boolean>
return this.http.get(`/api/isLogin`).map(item => {
return item[`success`];
});
}
}
複製程式碼
然後開啟根模組的routing模組, 注入AuthGuardService:
// /src/app/app-routing.module.ts
import { NgModule } from `@angular/core`;
import { RouterModule, Routes } from `@angular/router`;
import { AuthGuardService } from `./service/auth-guard.service`;
const appRoutes: Routes = [
{ path: `view`, loadChildren: `app/core/main/main.module#MainModule`, canActivate: [AuthGuardService] },
{ path: `schedule`, loadChildren: `app/core/schedule/schedule.module#ScheduleModule` },
{ path: `system`, loadChildren: `app/core/system/system.module#SystemModule` },
{ path: ``, redirectTo: `view/order`, pathMatch: `full` },
];
@NgModule({
imports: [RouterModule.forRoot(appRoutes, {
enableTracing: true, // <-- debugging purposes only
})],
exports: [RouterModule],
providers: [AuthGuardService]
})
export class AppRoutingModule {}
複製程式碼
以上會使整個模組的訪問受限,如果要設定特定元件是否可以訪問,則需要注入到相應的特性模組的routing模組,方法相同
CanDeactivate: 處理未儲存的修改
用非同步的方式等待伺服器答覆之前先停止導航,canDeactivate方法提供了當前元件,當前ActivatedRoute個RouterStateSnapshot例項。
下面這個Guard可以被所有元件複用
// /src/app/service/can-deactivate.service.ts
import { Injectable } from `@angular/core`;
import { CanDeactivate } from `@angular/router`;
import { CanDeactivate,
ActivatedRouteSnapshot,
RouterStateSnapshot } from `@angular/router`;
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable()
export class CanDeactivateService implements CanDeactivate<CanComponentDeactivate> {
canDeactivate (
component: CanComponentDeactivate,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
console.log(`Deactivate goes here`, component);
return component.canDeactivate ? component.canDeactivate() : true;
}
}
複製程式碼
當然也可以單獨為某個元件建立屬於他自己的canDeactivate-guard,建立完guard後,我們需要為元件建立他的canDeactivate()方法,這個方法返回一個Observable或Promise或boolean,最後加給routing模組對應route的canDeactivate陣列中即可;