代码之家  ›  专栏  ›  技术社区  ›  MarcoLe

RXJS-只发出比上一个值大的值

  •  -1
  • MarcoLe  · 技术社区  · 6 年前

    我想用rxjs为我的站点实现一个滚动监听器。侦听器当前发出每个滚动数字。如果数字比以前高,是否可以实现只发出滚动位置的滚动侦听器 . 我只想用操作员来解决这个问题。当前的实现如下所示:

      public lastScrolledHeight: number = 0;
      ...
      public ngOnInit() {
        this.listenForScroll()
          .subscribe(scrollHeight => {
            this.showAddButton = this.lastScrolledHeight >= scrollHeight; // true or false
            this.lastScrolledHeight = scrollHeight;
          });
      }
    
      private listenForScroll(): Observable<number> {
        return fromEvent(window, 'scroll').pipe(
          debounceTime(25),
          map((e: any) => e.path[1].scrollY)
        );
      }
    

    提示

    一种方法已经可以添加 startsWith(0) 接线员。会将初始位置发射到0。但是如果 scan() , filter() reduce() 会有帮助的,我说不出来。

    使用案例

    1 回复  |  直到 6 年前
        1
  •  1
  •   Daniel user3757731    6 年前

    你可以使用 scan 操作员和 distinctUntilChanged

    return fromEvent(window, 'scroll').pipe(
      debounceTime(25),
      map((e: any) => e.path[1].scrollY),
      scan((prev, curr) => Math.max(prev, curr), 0),
      distinctUntilChanged()
    )
    

    所发生的是,可观测值被修改为包含当前迭代和上一次迭代的最大值(其初始值为0)。

    在那之后 distinctUntilChanged()

    这样可以确保只接收大于上一个值的值。

        2
  •  2
  •   kos    6 年前

    我想,你可以用成对的:

    source$.pipe(
      startWith(-1),
      pairwise(),
      switchMap(([a,b])=>
        b > a
        ? of(b)
        : EMPTY
      )
    )
    

    RXJS - Only emit bigger values than the last value

    检查此代码 in a playground

    希望这有帮助

        3
  •  1
  •   MarcoLe    6 年前

    fromEvent(document, 'scroll').pipe(
          debounceTime(50),
          // get scrollY
          map((e: any) => e.path[1].scrollY),
          startWith(0),
          distinctUntilChanged(),
          // map the last scroll values into an array
          pairwise(),
          // returns true if delta of prev & curr is greaterOrEqual 0 => scroll up
          map(([prev, curr]: Array<number>) => prev - curr >= 0)
        );
    
        4
  •  1
  •   kos    6 年前

    由于对以前的方法不满意,我决定创建一个自定义运算符,它包含 rxjs.filter

    // it will take a predicate to compare values
    // by default it will behave as distinctUntilChanged()
    const filterChanges = (predicate = ((a,b) => a!==b)) => {
      // store previous value
      let prevValue = void 0;
      return pipe(
        filter((value, index)=>{
          // pass through the first value on stream
          if (index === 0) {
            prevValue = value;
            return value;
          }
    
          // compare current with prev
          const result = predicate(value, prevValue);
          prevValue = value;
          return result;
        })
      );
    };
    

    然后它就和传递一个比较器一样简单:

    source$.pipe(
      filterChanges((a, b) => a > b)
    )
    

    输出:

    filter changes custom operator

    这是一个 playground example .

    希望这有帮助