Angular NgRx:CustomRouterStateSerializer()被多次调用
我已经用常用的方法()为我的Angular项目实现了一个NgRx路由器存储 我的“问题”是,当通过单击组件的相应html元素触发routerLink时,我的Angular NgRx:CustomRouterStateSerializer()被多次调用,angular,ngrx,ngrx-store,ngrx-router-store,Angular,Ngrx,Ngrx Store,Ngrx Router Store,我已经用常用的方法()为我的Angular项目实现了一个NgRx路由器存储 我的“问题”是,当通过单击组件的相应html元素触发routerLink时,我的CustomRouterStateSerializer的serialize方法似乎被调用多次 您将在上找到以下描述的最小示例应用程序 我的实施 这是我的router.reducer.ts文件,其中包含RouterStateUrl接口和序列化程序类: 导出接口RouterStateUrl{ url:string; 查询参数:参数; 参数:参数
CustomRouterStateSerializer
的serialize方法似乎被调用多次
您将在上找到以下描述的最小示例应用程序
我的实施 这是我的
router.reducer.ts
文件,其中包含RouterStateUrl接口和序列化程序类:
导出接口RouterStateUrl{
url:string;
查询参数:参数;
参数:参数;
随机数;
}
导出类CustomRouterStateSerializer实现RouterStateSerializer{
序列化(routerState:RouterStateSnapshot):RouterStateUrl{
常量{url,根:{queryParams}}=routerState;
//随机数,以便以后能够将控制台输出与路由器状态相匹配(使用NgRx Store DevTools)
const random=Math.random();
warn(`CustomRouterStateSerializer被${url}调用,random:${random}`);
let状态:ActivatedRouteSnapshot=routerState.root;
while(state.firstChild){
state=state.firstChild;
}
const{params}=状态;
返回{url,queryParams,params,random};
}
}
这是我的app.module.ts
文件:
/*[…]*/
进口:[
/*[...],*/
StoreModule.forRoot(减速器、{
变质还原剂,
运行时检查:{
strictStateImmutability:true,
严格的不可更改性:true
}
}),
StoreDevtoolsModule.instrument({maxAge:25,logOnly:environment.development}),
EffectsModule.forRoot([AppEffects]),
StoreRouterConnectionModule.forRoot({
序列化程序:CustomRouterStateSerializer,
navigationActionTiming:navigationActionTiming.PostActivation,
}),
]
/*[...]*/
详细描述和输出 假设我的应用程序当前显示一些项目的概述(url:/projects),routerLink触发切换组件以显示作业概述(url:/jobs)。控制台将打印三条消息:
CustomRouterStateSerializer由/projects调用,随机:0.0896547559010431
CustomRouterStateSerializer由/jobs调用,随机:0.766202575297263
CustomRouterStateSerializer由/jobs调用,随机:0.079191760163307328
@ngrx/路由器存储/请求
router: {
state: {
url: '/projects',
queryParams: {},
params: {},
random: 0.31957045879116797
},
navigationId: 2
}
@ngrx/路由器存储/导航
router: {
state: {
url: '/jobs',
queryParams: {},
params: {},
random: 0.7662025752972623
},
navigationId: 3
}
@ngrx/路由器存储/导航
router: {
state: {
url: '/jobs',
queryParams: {},
params: {},
random: 0.7662025752972623
},
navigationId: 3
}
如您所见,@ngrx/路由器存储/导航
和@ngrx/路由器存储/导航
的状态相同。此外,它们的随机数与第二个控制台输出相同。@ngrx/router store/request
的随机数属于旧项目视图的状态
NgRx存储开发工具的输出似乎与预期一致。但是我不明白其他控制台输出是在什么时候调用serialize方法的。在任何状态下,我都找不到第一个和第三个控制台输出的任何随机数。现在我在问自己,我是否犯了错误(实现了一些东西),或者这只是正常的行为(但为什么?)。也许你们中的一些人可以告诉我。我尝试了一些东西,但最后它帮助我们了解了
@ngrx/router store
的源代码。
该模块的基本功能是监听所有路由器事件和调度操作。重要的代码如下:
但是我不明白其他控制台输出是在什么时候调用serialize方法的
您可以在这里看到有三种情况可以调用serialize()
:
- 在导航开始时(直接)
- 在
(通过NavigationEnd
和dispatchRouterNavigation()
方法)dispatchRouterNavigated()
- 在<代码>路线识别<代码>(通过<代码>调度路线激活()
serialize()
,以避免派生状态:路由器是路由器状态的来源,它可以在任何给定时间更改。
因此,当需要序列化状态时,它将不会存储在某个位置,而是每次新计算。
这就是函数被多次调用的原因。但是,由于序列化程序函数应该是纯函数,因此这根本不是问题,而是设计的一部分
在任何状态下,我都找不到第一个和第三个控制台输出的任何随机数
只会在导航
、取消
和错误
上将路由器状态放入存储,但不会在请求
和导航
上。
这意味着,您将在商店中看到的唯一随机数是源自导航操作的随机数。
所有其他的都只是“在路上”而已
现在我在问自己,我是否犯了错误(实现了一些东西),或者这只是正常的行为(但为什么?)
您的实现看起来不错,您可以放心了:这是正常的和预期的行为!我添加了一个关于StackBlitz的最小示例: