【问题标题】:Best way to loop through this array to display grouped Angular/html elements?循环遍历此数组以显示分组的 Angular/html 元素的最佳方法是什么?
【发布时间】:2021-10-18 17:20:19
【问题描述】:

我正在使用一个返回服务支付选项的 API。付款方式为(1 年服务,按月支付),(1 年服务,预付),(2 年服务,按月支付),(2 年服务,预付)。数据通过以下方式返回:

options = [
  { price: 10,
    serviceLength: "1 year",
    paymentFrequency: "monthly payment",
  },
  { price: 100,
    serviceLength: "1 year",
    paymentFrequency: "one-time payment",
  },
  { price: 8,
    serviceLength: "2 year",
    paymentFrequency: "monthly payment",
  },
  { price: 150,
    serviceLength: "2 year",
    paymentFrequency: "one-time payment",
  },
]

我需要以将 1 年服务选项和 2 年服务选项组合在一起的方式显示数据。像这样的:

1 年服务

  • 每月 - $XX.XX
  • 预付款:$XX.XX

2 年服务

  • 每月 - $XX.XX
  • 预付款:$XX.XX

为此组织数据的最佳方式是什么?未来可能会增加更多的价格选项。我在考虑有一个函数来分离年份长度,然后有一个双 for 循环来显示选项?

类似:

oneYearOptions = [
  { price: 10,
    serviceLength: "1 year",
    paymentFrequency: "monthly payment",
  },
  { price: 100,
    serviceLength: "1 year",
    paymentFrequency: "one-time payment",
  },

twoYearOptions = [
  { price: 8,
    serviceLength: "2 year",
    paymentFrequency: "monthly payment",
  },
  { price: 150,
    serviceLength: "2 year",
    paymentFrequency: "one-time payment",
  },
];

const allOptions = [oneYearOptions, twoYearOptions];

然后角度 ts 将类似于:

<div *ngFor="let option of allOptions>
   <div *ngFor="let priceOption of priceOptions">
     {{ list the data in here }}
   </div>
</div>

这对我来说只是效率低下。有一个更好的方法吗?也许改用哈希图?

【问题讨论】:

  • 坦率地说,考虑到您无法控制 API 返回数据格式,这似乎是一种合理的完成方式。通过不必将数组拆分为多个数组,您也许可以节省一些内存,但我认为没有必要这样做。至于速度性能,您将不得不遍历每个项目并显示它,因此您不能做得比“遍历每个项目”更好。
  • 如果您可以更改数据,如果您愿意,可以在一个循环中完成。您可以拥有一个包含对象的数组,其中对象可以具有诸如“标题”或选项之类的类型(其中选项是您现在拥有的对象)。

标签: javascript arrays angular multidimensional-array data-structures


【解决方案1】:

我认为我们可以在这里使用 groupBy 管道。

import { Component, Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name:"groupBy"
})
export class GroupBy implements PipeTransform {
  transform(array: any[]) : number {
    return array.reduce((trasnformedOption, { serviceLength })=>{
      if(!trasnformedOption.some(option => option.serviceLength === serviceLength)){
        trasnformedOption.push({
          serviceLength ,
          serviceDetails : array.filter(v=>v.serviceLength === serviceLength)
        });
      }
      return trasnformedOption;
    },[]);
  }
}

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  options = [
    { price: 10,
      serviceLength: "1 year",
      paymentFrequency: "monthly payment",
    },
    { price: 100,
      serviceLength: "1 year",
      paymentFrequency: "one-time payment",
    },
    { price: 8,
      serviceLength: "2 year",
      paymentFrequency: "monthly payment",
    },
    { price: 150,
      serviceLength: "2 year",
      paymentFrequency: "one-time payment",
    },
  ];
}

app.component.html

<div>
  <div *ngFor="let option of options | groupBy">
    {{ option.serviceLength }}
    <div *ngFor="let details of option.serviceDetails">
      {{ details.paymentFrequency}} - {{ details.price }}
    </div>
  </div>
</div>

【讨论】:

    【解决方案2】:

    如果您不想操作数据,也可以遍历数组的过滤版本:

    <div *ngFor="let option of options.filter(option => option.serviceLength == '1 year')">
         {{ list the data in here }}
    </div>
    <div *ngFor="let option of options.filter(option => option.serviceLength == '2 year')">
         {{ list the data in here }}
    </div>
    

    【讨论】:

      【解决方案3】:

      只是一个具有属性“选项”的对象,它是一个数组

      options =  
          {serviceLength: "1 year",
           options:[
            { price: 10,
             paymentFrequency: "monthly payment",
            },
            { price: 100,
             paymentFrequency: "one-time payment",
            }]
          },
          { serviceLength: "2 year",
            options:[
            { price: 8,
              paymentFrequency: "monthly payment",
            },
            { price: 150,
              paymentFrequency: "one-time payment",
            }]
          }
      ]
      

      确实,如果您将数据存储在 dbs 中,就像您的第一个对象数组一样,那么使用 reduce 转换为另一种方式是很好的

      this.options=this.data.reduce((a:any,b:any)=>{
          const el=a.find(x=>x.serviceLength==b.serviceLength)
          if (el){
            el.options=[...el.options,{price:b.price,paymentFrequency:b.paymentFrequency}]
            return a;
          }
           return [...a,{serviceLength:b.serviceLength,options:[{price:b.price,paymentFrequency:b.paymentFrequency}]}]
        },[])
      

      .html 变得像

      <div *ngFor="let option of options">
        <div>{{option.serviceLength}}</div>
        <!--see the inner .html loop over "option.options"-->
        <div *ngFor="let priceOption of option.options">
           {{ priceOption.price}} {{priceOption.paymentFrecuency}}
         </div>
      </div>
      

      一个fool stackblitz

      【讨论】:

        猜你喜欢
        • 2019-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-14
        • 1970-01-01
        • 2021-07-08
        • 2021-07-16
        • 2011-07-17
        相关资源
        最近更新 更多