【问题标题】:Rxjs, fromEvent handle multiple eventsRxjs, fromEvent 处理多个事件
【发布时间】:2021-07-02 09:20:23
【问题描述】:

我正在尝试使用fromEvent 组合多个事件blurkeyup (enter key only)。我已经实现了 blur 事件,我如何也可以组合 keyup.enter。

我已尝试使用 filter 运算符,但使用过滤器,输入正在工作 onblur 不是 -

Component.ts

this.propertyDescription.forEach((input: ElementRef) => {
    const events = ['blur', 'keyup'];
    from(events)
    .pipe(
        takeUntil(this.unsubscribe$),
        mergeMap((event) =>
            fromEvent(input.nativeElement, event)
        ),
        filter((e: KeyboardEvent) => e.key === 'Enter'),
        map((evt: any) => evt.target.value),
        distinctUntilChanged(
            (pre: any, curr: any) =>
                JSON.stringify(pre) === JSON.stringify(curr)
            )
        )
        .subscribe((caption: string) => {
            console.log(caption);
        });
});

【问题讨论】:

  • 您的过滤器不起作用,因为您只接受e.key === 'Enter' 的事件。如果你想要它得到keyup,你需要扩展它。我喜欢这里的其他建议。像查看每个事件的 if 语句一样查看过滤器。

标签: angular rxjs


【解决方案1】:
  1. forEach 内的订阅是一种不雅的设计。它会导致多个(可能未处理的)订阅。您可以将mergeArray#map 一起使用。

  2. 除了使用from,您还可以使用merge 和多个fromEvents。

试试下面的

const events = ['blur', 'keyup'];

merge(
  this.propertyDescription.map((input: ElementRef) =>
    merge(
      events.map((event: string) => 
        fromEvent(input.nativeElement, event).pipe(
          map((evt: any) => evt.target.value),
          distinctUntilChanged((pre: any, curr: any) =>
            JSON.stringify(pre) === JSON.stringify(curr)
          )
        )
      )
    )
  )
).pipe(
  takeUntil(this.unsubscribe$)
).subscribe((caption: string) => {
  console.log(caption);
});

【讨论】:

  • 收到此错误 - Type 'Observable<Observable<any>>' is not assignable to type 'string'
【解决方案2】:

您现在正在做的是将“blur”和“keyup”发送到您的主要可观察对象。

您需要做的是声明“keyup”事件的作用、“blur”事件的作用以及应用您的逻辑。

有点像:

this.propertyDescription.forEach((input: ElementRef) => {
  const blurEvent$ = fromEvent(input.nativeElement, 'blur').pipe(/* your logic for "blur" event */);
  const keyupEvent$ = fromEvent(input.nativeElement, 'keyup').pipe(/* your logic for "keyup" event */);
  merge(blurEvent$, keyupEvent$).pipe(
    takeUntil(this.unsubscribe$),
    /* rest of your logic */
  )
  .subscribe();
}

编辑: 合并不采用数组。 见stackblitz

【讨论】:

  • 订阅后我收到Observable {_isScalar: false, _subscribe: ƒ}。有没有办法直接从订阅中获取价值?
【解决方案3】:

在 Angular 中更好的方法是从模板发送事件

<input #inp (keyup.enter)="valueUpdates$.next(inp.value)" (blur)="valueUpdates$.next(inp.value)">


//ts
valueUpdates$ = new Subject<string>();


this.valueUpdates$
  .pipe(distinctUntilChanged())
  .subscribe((caption: string) => console.log(caption));

【讨论】:

    【解决方案4】:

    如果您只想在离开输入元素 (blur) 后或用户单击 Enter 后监听所做的更改,则可以改用 change 事件。

    但是,如果出于某种原因您明确希望将 blurkeyup 与 Enter 一起使用,则必须修复您的 filter 运算符。现在,您正在过滤掉所有没有key 属性且值为“Enter”的事件。 FocusEvent blur 没有那个属性,所以过滤器函数返回false

    一个有效的过滤器应该是这样的:

    filter((e: KeyboardEvent | FocusEvent) => e instanceof FocusEvent || e.key === 'Enter'),
    

    【讨论】:

      猜你喜欢
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      相关资源
      最近更新 更多