如何基于商品价格通过NgRx Effect条件触发模态框?
NgRx 实现商品价格超限检查并触发模态框
先修正现有代码的错误
1. 动作定义(补充明确语义)
原动作命名模糊且未携带参数,修正后:
// actions.ts import { createAction, props } from '@ngrx/store'; import { IProductListItem } from './reducer'; // 触发价格检查的动作 export const checkProductPrices = createAction('[Products] Check Product Prices'); // 检查到价格超限的动作(携带超限商品列表) export const productPriceExceeded = createAction( '[Products] Product Price Exceeded', props<{ products: IProductListItem[] }>() ); // 无价格超限的动作(可选) export const noProductPriceExceeded = createAction('[Products] No Product Price Exceeded');
2. 选择器(修复循环引用问题)
原选择器存在自引用错误,修正后:
// selectors.ts import { createSelector } from '@ngrx/store'; import { IProductsRequestState } from './reducer'; // 根选择器(替换为你的实际feature key,比如'productsRequest') export const selectProductsRequestState = (state: any) => state.productsRequest; // 获取商品列表数组的选择器 export const selectProductItems = createSelector( selectProductsRequestState, (state: IProductsRequestState) => state.list.items );
编写 Effect 核心逻辑
所有价格检查、模态框触发逻辑都在 Effect 中完成,无需组件介入:
// effects.ts import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; import { withLatestFrom, map, tap } from 'rxjs/operators'; import * as ProductActions from './actions'; import { selectProductItems } from './selectors'; import Swal from 'sweetalert2'; // 替换为你的sweetalert导入方式 @Injectable() export class ProductEffects { checkProductPrices$ = createEffect(() => this.actions$.pipe( // 监听触发检查的动作 ofType(ProductActions.checkProductPrices), // 从NgRx状态中获取最新的商品列表 withLatestFrom(this.store.select(selectProductItems)), // 过滤出价格超过10的商品 map(([_, products]) => products.filter(item => item.price > 10)), // 处理副作用:弹窗+分发动作 tap(exceededProducts => { if (exceededProducts.length > 0) { // 分发超限动作(可用于后续状态更新) this.store.dispatch(ProductActions.productPriceExceeded({ products: exceededProducts })); // 直接触发sweetalert模态框 Swal.fire({ title: '价格超限提示', text: `以下商品价格超过10:${exceededProducts.map(p => p.name).join(', ')}`, icon: 'warning', confirmButtonText: '知道了' }); } else { // 无超限情况分发对应动作 this.store.dispatch(ProductActions.noProductPriceExceeded()); } }) ), // 该Effect仅处理副作用,无需自动分发动作,设置dispatch: false { dispatch: false } ); constructor(private actions$: Actions, private store: Store) {} }
触发检查的时机
可以在商品列表加载完成后自动触发检查,比如在加载商品的Effect中:
// 示例:商品加载完成后触发价格检查 loadProductsSuccess$ = createEffect(() => this.actions$.pipe( ofType(ProductActions.loadProductsSuccess), // 替换为你的商品加载完成动作 map(() => ProductActions.checkProductPrices()) ) );
核心说明
- 所有业务逻辑(价格过滤、弹窗触发)都封装在NgRx Effect中,组件只需负责触发初始动作(如加载商品)
- 使用
withLatestFrom从状态中获取最新数据,遵循NgRx单向数据流原则 - 用
tap处理弹窗这类副作用,避免污染数据流 - 修正后的选择器可正确从状态中提取商品列表,避免循环引用错误
内容的提问来源于stack exchange,提问作者user28273827332
相关产品推荐
相关产品推荐

