angular6 路由路由守卫 CanDeactivate, 监听浏览器后退时,希望满足条件时跳到其他的路由
当我使用CanDeactivate 路由守卫来处理,从当前路由离开时的操作时,我会判断当前的路由页面的数据是否保存,如果没保存的话我就弹框提示,然后当用户点击是的时候,CanDeactivate 返回true, 就回到上一个路由,但是这时我期望的是,当我点击是的时候,跳转到别的路由,这时,就出出现了重复循环判断的问题。我该怎么处理
代码如下:
路由代码
export interface AbstractCanDeactivate {
canDeactivate();
}
@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<AbstractCanDeactivate> {
constructor(
private router: Router
) {
}
canDeactivate(
component: AbstractCanDeactivate,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
nextState: RouterStateSnapshot
): Observable<boolean> | boolean {
return component.canDeactivate();
}
}
弹框提示代码:
/**
* 回退判断
*/
canDeactivate() {
return Observable.create((observer) => {
if (!this.isSave) {
this.modalService.confirm({
nzTitle: '提示',
nzContent: '数据尚未认证,取消确认将返回我的订单?',
nzOnOk: async () => {
this.routeNavigate.navigate(['/setting/index/myOrder']);
observer.next(true);
},
nzOnCancel: () => {
observer.next(false);
}
});
} else {
observer.next(true);
}
});
}
注册 子模块的路由表 ,直接注册到了禁止回退的界面:
{ path: 'confirm', component: ConfirmOrderComponent , canDeactivate: [CanDeactivateGuard] },
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个 guard 只是一个 hook 函数,最终的返回值代表当前跳转行为的状态,在中间是可以利用 router 服务发起别的跳转的,这个例子在官方网站的文档中有,只不过例子中的 hook 是 canActive,你这里是 canDeactive。
Note: 在 hook 中调用 router 服务进行跳转,会直接中断当前路由的解析过程,这里的返回值只是为了使 guard 中的逻辑更加清晰而已,详见官方文档:
updated
抱歉回复晚了,昨天答案写了一半,然后突然有一些事情。结合你更新的反馈以及我之前项目写的一些代码,canActivate 和 canDeactivate 还是略微有一些区别,就是如果是前者,直接跳转时没有任何问题的,因为当前 guard 只会触发一次,而后者是有问题,因为每当要从当前路由跳转,都会调用一次 canDeactive 内部的逻辑,也就形成了你问题描述中提到的无限循环。
关于这点呢,我昨晚仔细思考了一下,之所以我项目中的代码能够运行,是因为之前将要跳转的目标 url 预先规定死了,当跳转目标路由是这个 url 时,直接返回 true,其背后应该是调用了两次 canDeactivate 内部的逻辑,但你这里应该是期望只调用一次。
如果是这样的话,这个跳转路由的逻辑不能放到 canDeactivate 这个 guard 内部了,而应该放到诸如 NavigationStart 等一系列的 RouterEvent 中,具体代码的话,看这个链接吧,示例中从 home 页面跳转任何一个其他页面都会提示,点击确定会跳转,点击取消会保留,应该和你这里的逻辑是一样的。
最后再说一点,就是这个问题在 github 的 issue 中也有曾被提及,提问者也是期望如果在 guard 中跳转新的路由跳转逻辑的话,不应当再次触发当前的 guard 了,而 angular-router 的作者的看法是,对于 guard 来讲,他希望其内部不要存在过多副作用(也就是指这里的跳转新的路由),因为这些副作用更好的发起时机是在 router 触发的一系列 RouterEvent 中,guard 应当尽可能的“纯”,从而符合单一职责原则。