angular6 路由路由守卫 CanDeactivate, 监听浏览器后退时,希望满足条件时跳到其他的路由

发布于 2022-09-11 14:44:00 字数 1568 浏览 20 评论 0

当我使用CanDeactivate 路由守卫来处理,从当前路由离开时的操作时,我会判断当前的路由页面的数据是否保存,如果没保存的话我就弹框提示,然后当用户点击是的时候,CanDeactivate 返回true, 就回到上一个路由,但是这时我期望的是,当我点击是的时候,跳转到别的路由,这时,就出出现了重复循环判断的问题。我该怎么处理

clipboard.png
代码如下:
路由代码

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情域 2022-09-18 14:44:00

这个 guard 只是一个 hook 函数,最终的返回值代表当前跳转行为的状态,在中间是可以利用 router 服务发起别的跳转的,这个例子在官方网站的文档中有,只不过例子中的 hook 是 canActive,你这里是 canDeactive。

Note: 在 hook 中调用 router 服务进行跳转,会直接中断当前路由的解析过程,这里的返回值只是为了使 guard 中的逻辑更加清晰而已,详见官方文档:

This secondary navigation automatically cancels the current navigation; checkLogin() returns false just to be clear about that.


updated
抱歉回复晚了,昨天答案写了一半,然后突然有一些事情。结合你更新的反馈以及我之前项目写的一些代码,canActivate 和 canDeactivate 还是略微有一些区别,就是如果是前者,直接跳转时没有任何问题的,因为当前 guard 只会触发一次,而后者是有问题,因为每当要从当前路由跳转,都会调用一次 canDeactive 内部的逻辑,也就形成了你问题描述中提到的无限循环。

关于这点呢,我昨晚仔细思考了一下,之所以我项目中的代码能够运行,是因为之前将要跳转的目标 url 预先规定死了,当跳转目标路由是这个 url 时,直接返回 true,其背后应该是调用了两次 canDeactivate 内部的逻辑,但你这里应该是期望只调用一次。

如果是这样的话,这个跳转路由的逻辑不能放到 canDeactivate 这个 guard 内部了,而应该放到诸如 NavigationStart 等一系列的 RouterEvent 中,具体代码的话,看这个链接吧,示例中从 home 页面跳转任何一个其他页面都会提示,点击确定会跳转,点击取消会保留,应该和你这里的逻辑是一样的。

最后再说一点,就是这个问题在 github 的 issue 中也有曾被提及,提问者也是期望如果在 guard 中跳转新的路由跳转逻辑的话,不应当再次触发当前的 guard 了,而 angular-router 的作者的看法是,对于 guard 来讲,他希望其内部不要存在过多副作用(也就是指这里的跳转新的路由),因为这些副作用更好的发起时机是在 router 触发的一系列 RouterEvent 中,guard 应当尽可能的“纯”,从而符合单一职责原则。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文