如何使用ngrx/router-store维护页面参数?含优先级规则
基于ngrx/router-store实现参数优先级逻辑的方案
我来帮你搞定这个需求!结合ngrx/router-store的特性,咱们可以通过路由参数监听+组合选择器的方式完美实现这个优先级规则,下面是具体步骤和代码示例:
1. 先定义Store中的参数状态结构
首先咱们得明确Store里要存的参数结构,比如假设我们要处理的是pageSize和currentPage这两个分页参数:
// 定义参数状态接口 export interface PageParamsState { pageSize: number | null; currentPage: number | null; } // 初始状态 export const initialPageParamsState: PageParamsState = { pageSize: null, currentPage: null, }; // 对应的Action,用于更新Store中的参数 export const updatePageParams = createAction( '[PageParams] Update Params', props<PageParamsState>() ); // Reducer export const pageParamsReducer = createReducer( initialPageParamsState, on(updatePageParams, (state, action) => ({ ...state, ...action, })) );
2. 用Router Store监听URL参数变化,更新Store
接下来要利用@ngrx/router-store提供的selectRouteParams选择器,监听URL中的参数变化,一旦URL里有参数,就自动更新Store中的对应值(因为URL参数优先级最高)。咱们写一个Effect来处理这个逻辑:
import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; import { routerNavigatedAction, selectRouteParams } from '@ngrx/router-store'; import { map, withLatestFrom } from 'rxjs/operators'; import { updatePageParams } from './page-params.actions'; @Injectable() export class PageParamsEffects { syncUrlParamsToStore$ = createEffect(() => this.actions$.pipe( ofType(routerNavigatedAction), withLatestFrom(this.store.select(selectRouteParams)), map(([_, routeParams]) => { // 从URL参数中提取值,注意URL参数都是字符串,需要转换类型 const pageSize = routeParams['pageSize'] ? parseInt(routeParams['pageSize'], 10) : null; const currentPage = routeParams['currentPage'] ? parseInt(routeParams['currentPage'], 10) : null; // 只要URL中有非空参数,就dispatch action更新Store return updatePageParams({ pageSize, currentPage }); }) ) ); constructor(private actions$: Actions, private store: Store) {} }
3. 创建组合选择器,实现优先级逻辑
现在核心的一步:写一个组合选择器,先检查URL参数是否存在,存在就用URL的;不存在就取Store里的;都没有就返回空。
import { createSelector } from '@ngrx/store'; import { selectRouteParams } from '@ngrx/router-store'; import { AppState } from '../app.state'; // 你的根状态类型 // 先获取Store中的参数 const selectPageParamsState = (state: AppState) => state.pageParams; // 创建最终的参数选择器 export const selectFinalPageParams = createSelector( selectRouteParams, selectPageParamsState, (routeParams, storeParams) => { // 处理pageSize:URL参数优先,其次Store,最后为空 const finalPageSize = routeParams['pageSize'] ? parseInt(routeParams['pageSize'], 10) : storeParams.pageSize ?? null; // 处理currentPage:同理 const finalCurrentPage = routeParams['currentPage'] ? parseInt(routeParams['currentPage'], 10) : storeParams.currentPage ?? null; return { pageSize: finalPageSize, currentPage: finalCurrentPage, }; } );
4. 在组件中使用这个选择器
最后在需要使用参数的组件里,订阅这个选择器就能拿到符合优先级规则的参数了:
import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { selectFinalPageParams } from './store/page-params.selectors'; import { Observable } from 'rxjs'; @Component({ selector: 'app-my-page', templateUrl: './my-page.component.html', }) export class MyPageComponent implements OnInit { pageParams$: Observable<{ pageSize: number | null; currentPage: number | null }>; constructor(private store: Store) { this.pageParams$ = this.store.select(selectFinalPageParams); } ngOnInit(): void { this.pageParams$.subscribe(params => { console.log('最终参数:', params); // 在这里用参数做业务逻辑,比如请求数据 }); } }
关键细节提醒
- URL参数默认都是字符串类型,一定要根据你的业务需求转换为对应类型(比如数字、布尔值)。
- 如果你的参数是可选的,要做好空值判断,避免出现
NaN或者意外错误。 - 这个方案支持路由变化时自动同步参数,不管是初始加载还是页面跳转,都能保证参数的优先级正确。
内容的提问来源于stack exchange,提问作者david30xie
相关产品推荐
相关产品推荐

