使用来自多个实体的数据创建@ngrx选择器(Angular)

时间:2018-06-11 05:58:30

标签: angular rxjs ngrx rxjs6 ngrx-entity

我的@ngrx实体基于以下模型:

export interface Product {
  id: number;
  code: string;
  text: string;
  brand: any;
  quantity_available: number;
  rate: number;
  // ... other variables
}

export interface BasketProduct {
  id: number; /*Product ID*/
  quantity: number;
  rate: number;
  value: number;
}

我将用户的个人资料存储在“设置”状态,并将所选过滤器(来自用户界面)存储在产品状态中:

export interface State extends EntityState<Setting> {
  // additional properties here
  user: {
    currency: {
      code: string,
      name: string,
    }
  };
}

export interface State extends EntityState<Product> {
  // additional properties here
  filters: {
    just_arrived: boolean;
    newly_launched: boolean;
    discounted: boolean;
    celebrity: boolean;
    niche: boolean;
    wish_list: boolean;
    search_text: string;
    brands;
    product_types;
    parent_companies;
  };
}

我的减速机的摘录如下:

export const selectAllProducts = createSelector(
  selectProductState,
  fromProduct.selectAllProducts
);

export const selectBasketProductEntities = createSelector(
  selectBasketState,
  fromBasket.selectBasketProductEntities
);

export const selectUserProfile = createSelector(
  selectSettingState,
  fromSetting.selectUserProfile
);

export const selectAllFilters = createSelector(
  selectProductState,
  fromProduct.selectAllFilters
);

然后我创建了一个选择器,用于合并上面选择器的数据:

// Returns the List of Products after applying Filters
    export const selectFilteredProducts = createSelector(
      selectAllProducts,
      selectAllFilters,
      selectBasketProductEntities,
      selectUserProfile,
      (products, filters, basket, userProfile) => {
        // Step 1: Filter the Products based on the Parameters
        const filtered = products.filter(
          product =>
            ((filters.just_arrived === false) ||
            (product.is_just_arrived === 1 && filters.just_arrived === true)) &&
            // ..... Additional Filters
        );

        // Step 2: Map the Quantity Selected / Currency Information
        return filtered.map(product => Object.assign({}, product, {
          quantity_selected: basket[product.id],
          currency: userProfile.currency.code
        }));
      }
    );

解决方案效果很好,但每当产品添加到购物篮时,我的整个产品列表都会重新初始化(可能是因为我正在使用地图重新分配产品)。随着产品列表的增长,这可能会产生性能问题。我想将更改检测限制为仅包含已更改的产品。

我在createSelector中的map / filter实现是否正确?如何提高性能?

1 个答案:

答案 0 :(得分:0)

很抱歉,但我没有看到其他明显的解决方案。 如果它是一个篮子,通常它不会包含数千件物品。没有? 如果是,也许您应该考虑使用后端进行过滤。

但是,在角度变化检测期间,性能可能会受到影响。 因此,您可以通过提供trackBy功能来改进。

<li *ngFor="let item of collection;trackBy: trackByFn">{{item.id}}</li>

See this post.

另一方面,为了更好的可读性,你可以写:

return filtered.map(product => {
      ...product,
      quantity_selected: basket[product.id],
      currency: userProfile.currency.code
    }));