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

如何通过NgRx-router-store将NavigationExtras存入状态管理仓库?

解决NgRx Router-Store获取NavigationExtras状态的问题

我来帮你搞定这个困扰!你当前用history.state的问题根源在于时机不匹配:当RouterStateSerializer执行serialize方法时,当前导航还未完全完成,浏览器的history.state还停留在上一次导航的状态,自然会拿到"下一次"的内容。下面给你两种可行的解决思路:

方案一:通过Effect捕获NavigationExtras并存入Store

这种方式不需要修改Serializer,而是利用NgRx的Effect监听导航事件,直接提取NavigationExtras里的状态存入独立的Store切片,更直观可控。

步骤1:定义设置导航状态的Action

import { createAction, props } from '@ngrx/store';

// 定义Action,用于将NavigationExtras的state存入Store
export const setNavigationExtraState = createAction(
  '[Router] Set Navigation Extra State',
  props<{ state: any }>()
);

步骤2:创建Effect监听导航事件

NgRx的routerNavigationAction会在每次导航时触发,它的payload里包含了完整的导航事件,其中就有我们需要的navigationExtras:

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { routerNavigationAction } from '@ngrx/router-store';
import { map } from 'rxjs/operators';
import { setNavigationExtraState } from './your-actions-file';

@Injectable()
export class RouterEffects {
  captureNavigationState$ = createEffect(() =>
    this.actions$.pipe(
      ofType(routerNavigationAction),
      map(action => {
        // 从导航事件中提取NavigationExtras的state
        const navExtraState = action.payload.event.navigationExtras.state;
        return setNavigationExtraState({ state: navExtraState });
      })
    )
  );

  constructor(private actions$: Actions) {}
}

步骤3:编写Reducer处理Action

在Reducer里创建一个专门的切片来存储导航状态:

import { createReducer, on } from '@ngrx/store';
import { setNavigationExtraState } from './your-actions-file';

// 定义导航状态的接口
export interface NavigationExtraState {
  data: any | null;
}

const initialState: NavigationExtraState = {
  data: null
};

export const navigationExtraReducer = createReducer(
  initialState,
  on(setNavigationExtraState, (state, { state: navState }) => ({
    ...state,
    data: navState
  }))
);

最后别忘了把这个Reducer加入到你的Store模块里,之后你就可以在任何组件/服务中通过Selector获取这个导航状态了。

方案二:修改RouterStateSerializer,缓存最新NavigationExtras

如果你希望把导航状态直接整合到router-store的routerState里,可以通过自定义服务缓存最新的NavigationExtras,再在Serializer中使用。

步骤1:创建导航状态缓存服务

这个服务会监听Angular的导航事件,缓存每次导航的navigationExtras:

import { Injectable } from '@angular/core';
import { Router, RouterNavigationEvent } from '@angular/router';
import { filter } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class NavigationExtraCacheService {
  private latestNavExtras: any | null = null;

  constructor(private router: Router) {
    // 监听RouterNavigationEvent(导航开始时触发),缓存navigationExtras
    this.router.events
      .pipe(filter(event => event instanceof RouterNavigationEvent))
      .subscribe((event: RouterNavigationEvent) => {
        this.latestNavExtras = event.navigationExtras.state;
      });
  }

  getLatestNavState(): any | null {
    return this.latestNavExtras;
  }
}

步骤2:修改你的RouterStateSerializer

注入缓存服务,用它来获取正确的导航状态,替代history.state:

import { RouterStateSerializer, RouterStateSnapshot } from '@ngrx/router-store';
import { Injectable } from '@angular/core';
import { NavigationExtraCacheService } from './navigation-extra-cache.service';

export interface IRouterStateUrl { 
  url: string; 
  params: any; 
  state: any; 
}

@Injectable()
export class AppRouterStateSerializer implements RouterStateSerializer<IRouterStateUrl> {
  constructor(private navCacheService: NavigationExtraCacheService) {}

  serialize(routerState: RouterStateSnapshot): IRouterStateUrl {
    const { url } = routerState;
    const params = routerState.root.firstChild ? routerState.root.firstChild.params : {};
    // 从缓存服务获取当前导航的state
    const state = this.navCacheService.getLatestNavState();
    return { url, params, state };
  }
}

步骤3:确保Serializer正确配置

在你的Store模块中,确保StoreRouterConnectingModule使用了这个自定义Serializer:

import { StoreRouterConnectingModule } from '@ngrx/router-store';
import { AppRouterStateSerializer } from './app-router-state-serializer';

@NgModule({
  imports: [
    // ...其他模块
    StoreRouterConnectingModule.forRoot({
      serializer: AppRouterStateSerializer
    })
  ]
})
export class AppStoreModule {}

这样修改后,router-store中的routerState就会包含当前导航的NavigationExtras状态了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:29:53