通过一个实际的例子学习 combineLatest

举报
Jerry Wang 发表于 2022/10/03 10:08:37 2022/10/03
【摘要】 我开发了一个简单的 Angular 应用来展示这个 rxjs Operator 的用法,地址如下:https://jerry-combine.stackblitz.io/其中 limit 控制 list 元素显示个数,而 offset 控制显示元素的索引:例如我将 offset 改为 1 时,显示的元素 从 ivysaur 开始:首先我设计了一个 form 表单,里面包含了两个 input ...

我开发了一个简单的 Angular 应用来展示这个 rxjs Operator 的用法,地址如下:

https://jerry-combine.stackblitz.io/

其中 limit 控制 list 元素显示个数,而 offset 控制显示元素的索引:

例如我将 offset 改为 1 时,显示的元素 从 ivysaur 开始:

首先我设计了一个 form 表单,里面包含了两个 input 控件,分别维护 limit 和 offset:

<form>
    <mat-form-field class="example-full-width">
      <input matInput placeholder="Limit" [formControl]="limitControl" type="number">
    </mat-form-field>
    <mat-form-field class="example-full-width">
      <input matInput placeholder="Offset" [formControl]="offsetControl" type="number">
    </mat-form-field>
  </form>

limitControl 和 offsetControl 是我在组件里定义的两个 public 属性:

limit$ 的数据源:来自 limitControl.valueChanges.

 const limit$ = this.limitControl.valueChanges
      .pipe(
        startWith(this.limitControl.value),
        // Needed to fix a bug where inputs with type number emit twice
        // https://github.com/angular/angular/issues/12540
        distinctUntilChanged(),
      );

注意这里使用了一个 distinctUntilChanged,也就是说如果 limit$ 的值没有发生变化时,不会向下游 emit 数据。

pokemon$ 的数据源:

this.pokemon$ = combineLatest(limit$, offset$)
      .pipe(
        map(data => ({limit: data[0], offset: data[1]})),
        switchMap(data => this.pokemonService.getPokemon(data.limit, data.offset)),
        map((response: {results: Pokemon[]}) => response.results),
      );

注意代码第 62 行的 data,数据结构为数组,第一个元素是 limit$ 包含的值,第二个元素为 offset$ 包含的值:

这两个值经过 map 处理后,投递给服务 pokemonService.

最后将该服务返回的 Response,通过 ngFor 展开,显示成列表。

最后渲染出的列表数据如下图所示:

https://pokeapi.co/api/v2/pokemon/?offset=7&limit=6 这个 api 在公网上可以用于学习目的使用:

这里有一个小问题:每次我在浏览器里修改 limit 的值时:

form control 的 valueChanges 事件会触发两次:

这是 Angular 框架一个已知的问题:

https://github.com/angular/angular/issues/12540

为了使用 formControl 这个指令,我们需要在 appmodule 里导入如下 module:

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

而 app 组件模板里使用的元素 mat-form-field 等等,来自 Angular material design module:

import { MatInputModule } from '@angular/material/input';
import { MatCardModule } from '@angular/material/card';
import { MatTableModule } from '@angular/material/table';
import { MatButtonModule } from '@angular/material/button';

如下图所示:

需要 package.json 里显式定义这些依赖:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。