使用 RxJS 创建可过滤列表

Creating a filterable list with RxJS

我正在尝试进入响应式编程。我一直使用 map、filter 和 reduce 等数组函数,并且喜欢我可以在不创建状态的情况下进行数组操作。

作为练习,我尝试在不引入状态变量的情况下使用 RxJS 创建可过滤列表。最后它应该像这样工作:

我知道如何使用天真的 JavaScript 或 AngularJS/ReactJS 来完成此操作,但我正在尝试仅使用 RxJS 并且不创建状态变量来完成此操作:

var list = [
  'John',
  'Marie',
  'Max',
  'Eduard',
  'Collin'
];

Rx.Observable.fromEvent(document.querySelector('#filter'), 'keyup')
  .map(function(e) { return e.target.value; });

// i need to get the search value in here somehow:
Rx.Observable.from(list).filter(function() {}); 

现在如何将搜索值获取到我从列表创建的可观察对象的过滤函数中?

非常感谢您的帮助!

您需要包装 from(list),因为每次更改过滤器时都需要重新启动可观察列表。由于这种情况经常发生,您可能还希望在过滤器太短时阻止过滤,或者如果在短时间内有另一个击键。

//This is a cold observable we'll go ahead and make this here
var reactiveList = Rx.Observable.from(list);

//This will actually perform our filtering
function filterList(filterValue) {
  return reactiveList.filter(function(e) {
   return /*do filtering with filterValue*/;
  }).toArray();
}


var source = Rx.Observable.fromEvent(document.querySelector('#filter'), 'keyup')
  .map(function(e) { return e.target.value;})

  //The next two operators are primarily to stop us from filtering before 
  //the user is done typing or if the input is too small
  .filter(function(value) { return value.length > 2; })
  .debounce(750 /*ms*/)

  //Cancel inflight operations if a new item comes in.
  //Then flatten everything into one sequence
  .flatMapLatest(filterList);

//Nothing will happen until you've subscribed
source.subscribe(function() {/*Do something with that list*/});

这全部改编自 RxJS 的标准示例之一 here

你可以在这里看看我是怎么做到的: https://github.com/erykpiast/autocompleted-select/

它是端到端的解决方案,抓取用户交互并将过滤后的列表呈现给 DOM。

您也可以看看 WebRx's List-Projections

Live-Demo

披露:我是该框架的作者。

您可以创建一个新流,获取人员列表和 keyups 流,合并它们并扫描以过滤后者。

const keyup$ = Rx.Observable.fromEvent(_input, 'keyup')
  .map(ev => ev.target.value)
  .debounce(500);

const people$ = Rx.Observable.of(people)
  .merge(keyup$)
  .scan((list, value) => people.filter(item => item.includes(value)));

这样你将拥有:

-L----------------人物名单

-----k-----k--k---- keyups 流

-L----k-----k--k----合并流

然后就可以扫描了。正如文档所说:

Rx.Observable.prototype.scan(accumulator, [seed])

Applies an accumulator function over an observable sequence and returns each intermediate result.

这意味着您将能够过滤列表,将新列表存储在累加器中。

订阅后数据为新列表。

people$.subscribe(data =>  console.log(data) ); //this will print your filtered list on console

希望它helps/was够清楚