【问题标题】:Creating a filterable list with RxJS使用 RxJS 创建可过滤列表
【发布时间】:2015-05-29 13:00:30
【问题描述】:

我正在尝试进入响应式编程。我一直在使用 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() {}); 

现在如何将搜索值输入到我从列表中创建的 observable 的过滤器函数中?

非常感谢您的帮助!

【问题讨论】:

    标签: javascript functional-programming reactive-programming rxjs reactive-extensions-js


    【解决方案1】:

    您需要包装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 的标准示例之一

    【讨论】:

      【解决方案2】:

      您可以创建一个新流,获取人员列表和 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])

      在可观察序列上应用累加器函数并返回每个 中间结果。

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

      订阅后,数据将成为新列表。

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

      希望它有帮助/足够清楚

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

          Live-Demo

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-23
            • 2020-07-23
            • 2019-08-03
            • 2013-11-04
            • 2019-03-03
            • 1970-01-01
            相关资源
            最近更新 更多