我已经完成了一系列教程,完成了演示等等。但是我仍然无法用正确的方式绕过Observables这样做...
基本上我拥有的(在角度上)是我的组件中的2个可变数组,一个displayList和一个完整的项目列表...模板在displayList上执行ngFor。
屏幕上的过滤器调用清除displayList的组件中的过滤器函数,然后循环遍历fullList,如果过滤器适用,则将其推送到显示列表 - 在屏幕上给出实时列表过滤效果...
我知道这是解决这个问题的错误方法,但我无法用可观察的方式来解决这个问题所需的架构/模式。我是否根据组件私有属性制作主列表并在其上运行.filter()?我是否在返回带有.filter的可观察列表的方法上执行ngFor?
提前致谢。
答案 0 :(得分:2)
是,是,否,是,否......换句话说:没有正确的答案,这取决于。 (关于您的个人,偏好,一般用例,应用程序的现有架构,等等......)
在控制器中过滤
在您的情况下,可能不需要rxjs,但如果可能的话,您应该避免使用可变对象/数据,因此使用.filter
的想法将是这里的方法。
自定义管道
另一种方法是实现自定义管道并直接在模板中过滤数据:
<div *ngFor="let item of fullList | customFilterPipe:filterSettings">...</div>
RxJS-Way
既然你要求rxjs-way,我就是这样做的:
filterSettings$: BehaviorSubject<IFilterData> = new BehaviorSubject(INITIAL_FILTER_SETTINGS); // this is updated with filterSettings$.next(newFilterSettings)
fullList$: BehaviorSubject<IData[]> = new BehaviorSubject([]); // updated through fullList$.next(newFullList);
displayList$ = Observable.combineLatest(this.fullList$, this.filterSettings$)
.map(([list, filterSettings]) => {
return list.filter(/* your custom filter based on the filterSettings... */);
});
每当displayList$
或filterSettings$
更改时,这都会自动更新fullList$
。
要在模板中使用它,您可以使用async
- 管道:
<div *ngFor="let item of displayList$ | async">...</div>
但同样:对于特定情况,任何这些解决方案以及您当前的实现都可能是完全有效的实现。
答案 1 :(得分:2)
在RxJS 5中,最好的候选者是combineLatest()
运算符(它有静态和实例方法变体),当它的任何源Observable发出一个值时,它调用它的选择器函数。
let userInput$ = Observable.from(['a', 'ac', 'aca', 'acarp'])
.concatMap(char => Observable.of(char).delay(500))
.startWith(null);
let list$ = Observable.of(['abstemious', 'abstentious', 'abulia', 'abut', 'aby', 'acalculia', 'acarophobia', 'acarpous', 'accidence', 'accismus', 'acclamation']);
let filteredList$ = Observable.combineLatest(list$, userInput$, (list, filterString) => {
if (filterString) {
// Note that this is Array.filter() method, not an RxJS operator
return list.filter(name => name.indexOf(filterString) === 0);
}
return list;
});
filteredList$.subscribe(val => console.log(val));
查看现场演示:https://jsbin.com/jihuxu/2/edit?js,console
这模拟了用户每500毫秒键入一个字符并相应地过滤list$
的情况。请注意,list$
也可以发出一个可以立即过滤的新数组。
需要注意的一件重要事情是,每个源Observable必须在.combineLatest()
能够在每次更改时发出至少一个值。这就是为什么我还有startWith(null)
,以确保所选过滤器在开头是null
。