You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NgRx中从Router_Cancel事件获取之前的路由状态?

NgRx + CanDeactivate守卫:取消导航后路由状态未同步的解决方案

嘿,我刚好碰到过和你一模一样的问题!咱们来一步步解决它:

问题根源

当你触发导航时,NgRx的路由模块会先派发Router_Navigation事件更新Store状态,不管后续CanDeactivate守卫是否允许导航。如果守卫阻止了导航,虽然Router_Cancel事件会触发,但默认情况下NgRx不会自动把路由状态回滚到之前的页面,这就是问题所在。

解决方案步骤

  • 创建一个处理路由取消的Effect
    我们需要监听Router_Cancel事件,手动把Store里的路由状态恢复到导航前的状态:

    import { Injectable } from '@angular/core';
    import { Actions, createEffect, ofType } from '@ngrx/effects';
    import { RouterCancelAction, ROUTER_CANCEL } from '@ngrx/router-store';
    import { tap } from 'rxjs/operators';
    import { Store } from '@ngrx/store';
    import { routerNavigatedAction } from '@ngrx/router-store';
    
    @Injectable()
    export class RouterEffects {
      restoreRouteOnCancel$ = createEffect(() =>
        this.actions$.pipe(
          ofType<RouterCancelAction>(ROUTER_CANCEL),
          tap((action) => {
            // 从取消事件中获取导航前的原始路由状态
            const previousRouterState = action.payload.routerState;
            // 派发routerNavigatedAction来重置路由状态
            this.store.dispatch(routerNavigatedAction({
              routerState: previousRouterState,
              event: action.payload.event,
              url: action.payload.event.url,
              navigationId: action.payload.event.id
            }));
          })
        ),
        { dispatch: false } // 手动派发了action,所以这里设为false避免重复触发
      );
    
      constructor(private actions$: Actions, private store: Store) {}
    }
    
  • 确保路由状态序列化正确
    要保证你的路由状态序列化器能正确处理路由信息,这样恢复状态时才能精准回到导航前的页面。如果有自定义序列化逻辑,要确认previousRouterState能被正确解析。

  • 验证守卫逻辑
    确认你的CanDeactivate守卫在需要阻止导航时,正确返回false或者Observable<false>,这样Router_Cancel事件才会被NgRx正确触发。

额外说明

你在NgRx文档里看到的ROUTER_CAN_DEACTIVATE,主要是用来让你在CanDeactivate守卫中访问Store的状态,和我们现在要解决的状态回滚问题没有直接关联。上面的方案是目前处理这类问题最直接有效的方式。

内容的提问来源于stack exchange,提问作者kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:32:46