RxJS Observables和构建过滤列表的正确方法

时间:2017-03-02 14:40:47

标签: angular rxjs observable

我已经完成了一系列教程,完成了演示等等。但是我仍然无法用正确的方式绕过Observables这样做...

基本上我拥有的(在角度上)是我的组件中的2个可变数组,一个displayList和一个完整的项目列表...模板在displayList上执行ngFor。

屏幕上的过滤器调用清除displayList的组件中的过滤器函数,然后循环遍历fullList,如果过滤器适用,则将其推送到显示列表 - 在屏幕上给出实时列表过滤效果...

我知道这是解决这个问题的错误方法,但我无法用可观察的方式来解决这个问题所需的架构/模式。我是否根据组件私有属性制作主列表并在其上运行.filter()?我是否在返回带有.filter的可观察列表的方法上执行ngFor?

提前致谢。

2 个答案:

答案 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