何时使用
- 用户无权导航到目标组件
- 用户得先登录认证
- 显示目标组件前,需要先获得某些数据
- 离开组件前,需要先保存修改,需要询问用户是否放弃修改
使用方法
-
路由守卫返回一个值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数组中即可;