它有内置管道吗?
data = [
{id: 5, name: 'Roger'},
{id: 5, name: 'Mark'},
{id: 5, name: 'Zach'},
{id: 5, name: 'Mark'},
{id: 5, name: 'Roger'},
];
<ul>
<li *ngFor="let datum of data">
{{datum.name}}
</li>
</ul>
Output
Desired Output
答案 0 :(得分:11)
您可以创建自己的管道。
import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash';
@Pipe({
name: 'unique',
pure: false
})
export class UniquePipe implements PipeTransform {
transform(value: any): any{
if(value!== undefined && value!== null){
return _.uniqBy(value, 'name');
}
return value;
}
}
您需要在组件中添加UniquePipe,然后在HTML文件中添加管道。
<ul>
<li *ngFor="let datum of data | unique">
{{datum.name}}
</li>
</ul>
答案 1 :(得分:6)
这有点旧,但我想为未来找到这个的人添加一个答案。
接受的答案建议使用实现目标的管道,但在这种情况下不是推荐的方法。这里我们讨论的是列表过滤器,一个非常具体的复制过滤器。最糟糕的情况是此操作上的大O可能接近n ^ 2或者相当大的内存密集(取决于您的方法),并且管道操作在每个更改检测周期执行,并且非常频繁地更改Angular触发器中的检测。如果此列表非常长,或者如果您对此进行了练习,那么您的应用程序将停止运行并且您将遇到明显的性能问题。
Angular 1实际上包含了一个“过滤器”管道,但团队选择在角度2中摆脱它,因为过滤管道的滥用导致人们将角色1归咎于这种不良做法导致的性能问题。管道用于非常小的数据转换,例如格式化数字或字符串。
你应该这样做的方法是在代码中过滤你的列表,并构建逻辑以自己触发过滤(例如当你的列表实际发生变化时),而不是依靠变化检测来为你做。在这种情况下很难确切地说明如何执行此操作,因为它非常特定于用例,如果您希望应用程序运行良好,则应该如此。一个相当通用的例子是如果这个列表来自一个可观察的流(应该如此),那么只需在map运算符中执行此操作并使用async,如下所示:
dataSource = Observable.of(data); //this is just for example, the actual data source should be an http call or some service layer subject that you can actually update / trigger
uniqueData$ = this.dataSource.map(data => _.uniqBy(data, 'name'));
<ul>
<li *ngFor="let datum of uniqueData$ | async">
{{datum.name}}
</li>
</ul>
这里的优点是过滤操作仅在可观察流触发时触发,因此您可以非常高地控制何时进行过滤,并且仍然非常容易推理并且非常“确定正确”#