Angular 如何在字段更新后执行函数。但是不是在每次更改时都这样做,而是在更改了 3 或 4 个字母之后

Blo*_*orn 0 directive onchange call angular

我有一个角度形式,我想建议用户根据他正在写的内容在输入中输入什么。

我显然可以使用指令 onChange 并对服务进行 api 调用,该服务在每次更改后提出建议。但我认为这不是一个好的实现,因为我会做与用户写的字母一样多的调用(以及可能的拼写错误)。所以这个想法是让这个 onChange 函数只在对字段进行 X 更改后才进行 api 调用。我怎样才能做到这一点?如何检查该字段是否已更改到足以进行另一个 api 调用以获取新建议?

Shr*_*van 5

首先,您必须监听表单输入字段的更改。如果您使用的是 Reactive Angular 表单,那么您可以使用 formControl 的valueChanges属性来监听更改。否则,您必须使用@ViewChild装饰器来获取 TS 文件中输入元素的引用,然后使用 RXJSfromEvent函数监听更改。

我已经使用 RXJS fromEvent 函数进行演示。根据您的需要随意修改它。

export class AppComponent implements OnInit {
  @ViewChild('textbox', { static: true }) textbox: ElementRef<HTMLInputElement>;

  ngOnInit() {
    /**
     * If you are using Reactive form, then use
     * form.get('<form-control-name>').valueChanges
     */
    const inputChanges$ = fromEvent(this.textbox.nativeElement, 'keyup');
    inputChanges$
      .pipe(
        // remove the below map operator if you are using Reactive forms formControl
        map(event => (event.target as HTMLInputElement).value),
        debounceTime(500),
        distinctUntilChanged(),
        switchMap(val => {
          // perform the http call for your service API like below
          // return this.http.get(`service.com/get?search=${val}`)
          return of(`sevice api all for: ${val}`);
        })
      )
      .subscribe(console.log)
  }
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,所有繁重的工作都是由这 3 个 RXJS 操作符完成的debounceTimedistinctUntilChangedswitchMap

  1. 去抖动时间:

此过滤器运算符仅在特定时间段后才发出值,如果在此时间跨度内发出多个值,则仅返回最后一个值。例如,如果 debounceTime 设置为 500 毫秒(在我们的例子中),只有每 500 毫秒发出的最后一个值通过这个过滤器操作符。有关更多信息,请访问Rxjs 官方文档

debounceTime 是比计算更改的字母数以防止每次更改都调用 API 更好的解决方案。此外,不要过多地增加 denounceTime,因为它可能会破坏用户体验。

  1. distinctUntilChanged:

顾名思义,仅当收到的最新值与前一个值不同时,值才会通过此过滤器运算符。有关更多信息,请访问Rxjs 官方文档

  1. 开关映射:

这是一个高阶映射运算符,从某种意义上说,它为给定的输入返回一个 observable。这在我们的例子中特别有用,因为对于每个输入元素值的变化,我们需要点击后端服务 API 来获取一些值以供建议。关于这个操作符最有趣的部分是,当它接收到一个新值时,当一个异步服务调用正在进行前一个值时,它会取消前一个请求并发送一个新的请求来获取最新的值。

我强烈建议您阅读这篇文章,因为switchMap使用 opreator时会发生很多事情,我无法在这里解释所有内容。了解此运算符背后的概念很重要。

记住不要手动订阅 switchMap 操作符中的 observable。这个 RXJS 操作符会自动订阅新的 observable 并取消订阅旧的 observable。

您可以在我的示例Stackblitz 应用程序中查看此示例的源代码。

编辑:更新链接和参考