我开发了一个简单的 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 里显式定义这些依赖: 更多Jerry的原创文章,尽在:"汪子熙"。 |
|