1. 引子
假设我们需要一个过滤管道来负责过滤应用程序中的列表。
1 | import { Pipe, PipeTransform } from '@angular/core'; |
2 | |
3 | ({ |
4 | name: ‘filter’ |
5 | }) |
6 | export class FilterPipe implements PipeTransform { |
7 | transform(arr: string[], searchValue: string) { |
8 | if (!searchValue) return arr; |
9 | |
10 | return arr.filter(value => { |
11 | return value.toLowerCase().indexOf(searchValue.toLowerCase()) > -1; |
12 | }); |
13 | } |
14 | } |
这里我们创建来一个数组,通过indexOf方法过滤数组中的元素,最终得到我们想要的列表。
使用方式如下:
1 | import { Component } from '@angular/core'; |
2 | import { FormControl } from '@angular/forms'; |
3 | |
4 | @Component({ |
5 | selector: ‘my-app’, |
6 | template: ` |
7 | <input [formControl]="search"> |
8 | |
9 | <div *ngFor=”let item of (items | filter:search.value)”> |
10 | {{item}} |
11 | </div> |
12 | ` |
13 | }) |
14 | export class AppComponent { |
15 | search = new FormControl(); |
16 | items = [‘One’, ‘Two’, ‘Three’, ‘Four’]; |
17 | } |
2. 问题
以上很完美解决了列表过滤的需求,但是这个时候产品想向用户展示检索结果集的数量。大多数时候,我们可能会想,不就是一个数组长度的事儿,有什么难的,然后codeing如下:
1 | <div *ngFor=”let item of (items | filter:search.value)”> |
2 | {{item}} |
3 | </div> |
4 | <p>Count: <b>{{(items | filter:search.value).length}}</b></p> |
但是,真不要这么干!你会发现我们写的管道会运行两次。angular4之后这个问题有了解决方案,那就是: as。借助as关键字将管道结果分配给局部变量,还等什么,升级改进我们的代码如下:
1 | <div *ngFor=”let item of (items | filter:search.value) as result”> |
2 | {{item}} |
3 | </div> |
4 | {{result.length}} |
这个时候你会发现控制台报错了…
1 | Cannot read property ‘length’ of undefined |
这不是玩我吗?有局部变量啊,为啥还会报错,解决方案是: ngIf
最终的code如下:
1 | <ng-container *ngIf=”(items | filter:search.value) as result”> |
2 | |
3 | <div *ngFor=”let item of result”> |
4 | {{item}} |
5 | </div> |
6 | |
7 | <p>Count: <b>{{result.length}}</b></p> |
8 | |
9 | </ng-container> |