合理配置和管理路由守卫形成有效守卫链
- CanActivate:用于决定是否可以激活路由。通常放在首位,例如在用户登录验证场景,判断用户是否已登录。在
app-routing.module.ts
中配置如下:
const routes: Routes = [
{
path: 'protected-route',
component: ProtectedComponent,
canActivate: [AuthGuard]
}
];
- Resolve:在路由激活之前获取数据。比如在展示商品详情页时,提前获取商品数据。配置方式如下:
const routes: Routes = [
{
path: 'product/:id',
component: ProductComponent,
resolve: {
product: ProductResolver
}
}
];
- CanDeactivate:用于决定是否可以离开当前路由。常用于防止用户未保存表单数据就离开页面。在目标组件所在路由配置:
const routes: Routes = [
{
path: 'edit-form',
component: EditFormComponent,
canDeactivate: [CanDeactivateGuard]
}
];
- 守卫链顺序:一般按照
CanActivate
-> Resolve
-> CanDeactivate
(离开当前路由时)的顺序执行。在配置路由时,确保各个守卫按此逻辑顺序添加。
处理异步操作及错误情况
- 异步操作处理
- CanActivate和Resolve:这两个守卫可以返回
Observable<boolean>
或Promise<boolean>
来处理异步操作。例如,在AuthGuard
的canActivate
方法中进行异步登录验证:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
import { map, take } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return this.authService.isLoggedIn.pipe(
take(1),
map((isLoggedIn: boolean) => {
if (!isLoggedIn) {
this.router.navigate(['/login']);
return false;
}
return true;
})
);
}
}
- **CanDeactivate**:同样可以返回`Observable<boolean>`或`Promise<boolean>`。例如在`EditFormComponent`离开时,提示用户保存表单:
import { Injectable } from '@angular/core';
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { EditFormComponent } from './edit-form.component';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<EditFormComponent> {
canDeactivate(
component: EditFormComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (component.isFormDirty) {
return window.confirm('你有未保存的数据,确定离开吗?');
}
return true;
}
}
- 错误情况处理
- CanActivate和Resolve:如果异步操作失败,例如
AuthGuard
中登录验证失败,可以通过Router
服务导航到错误页面或登录页面。如上述AuthGuard
示例中,验证失败导航到/login
。
- CanDeactivate:如果用户选择不离开(返回
false
),则保持在当前路由。如果出现错误(如异步操作异常),可以通过console.error
记录错误,并返回false
阻止离开,同时可以弹出提示框告知用户。