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

如何基于商品价格通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 15:28:16