管道

管道在数据显示时,把一个输入转换成另一个输出
可以看作一个函数,或者作为一个用来格式化数据的工具

首先在类中定义一个日期变量:

app.component.ts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { Component, OnInit, OnChanges } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{
  birthday = new Date(1998, 1, 1);
}

然后在html中显示出来:

app.component.html:

1
<span>{{ birthday | date }}</span>

"|"就代表管道操作符,date是angular中自带的管道函数
这个管道的操作是将birthday这个日期型的变量转换成了格式化过的日期,运行的效果如下:

pipe1

angular中内置了很多管道,可以参考以下链接:
https://angular.cn/api?type=pipe

管道参数

管道可以看作一个函数,所以也可以传入参数

根据之前的例子,app.component.ts不变,html改成如下:

app.component.html:

1
<span>{{ birthday | date:"MM/dd/yy" }}</span>

管道函数后加冒号就可以传入参数,上面例子中的写法意思是将日期以“MM/dd/yy”的格式输出,效果如下:

pipe2

参数可以是任何值,上面的例子直接传入了一个字符串,也可以定义一个变量然后传入

在类中新加一个变量format,并增加一个方法:

app.component.ts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import { Component, OnInit, OnChanges } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{
  birthday = new Date(1998, 1, 1);
  format: String = "shortDate";

  changeFormat(){
    if(this.format == "shortDate"){
      this.format = "fullDate";
    } else {
      this.format = "shortDate";
    }
  }
}

然后在html中写入:

1
2
<span>{{ birthday | date:format }}</span><br/>
<button (click)="changeFormat()">changeFormat</button>

运行后点击按钮,日期就会在短格式和完整格式中切换

链式管道

可以把管道串在一起,达到多次格式化的效果

1
<span>{{ birthday | date | uppercase }}</span>

以上的例子会按顺序从左到右,先将birthday格式化,然后将格式化后的字符串转换成大写

自定义管道

你可以写自己的自定义管道
首先新建一个类,然后写入:

birthday-format-pipe.ts:

1
2
3
4
5
6
7
8
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'birthdayFormat'})
export class BirthdayFormatPipe implements PipeTransform {
  transform(value: Date, exponent?: string): string {
    return exponent + "'s birthday is :" + value.getFullYear() + "/" + value.getMonth() + "/" + value.getDay();
  }
}

这个管道类实现了从@angular/core引入的PipeTransform接口,接受了一个输入值(value: Date)和一些可选参数(exponent?: string),处理后输出了一个string值
通过 @Pipe 这个装饰器告诉了angular这是一个管道,装饰器也是从@angular/core中引入的
@Pipe装饰器中自定义了管道的名字,这个类中管道的名字是“birthdayFormat”

然后在app.module.ts中将这个管道导入进来:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BirthdayFormatPipe } from './birthday-format-pipe';    //导入管道

@NgModule({
  declarations: [
    AppComponent,
    BirthdayFormatPipe  //导入管道
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

然后在html中写入:

app.component.html:

1
<span>{{ birthday | birthdayFormat:"ABC" }}</span>

效果如下:

pipe3

管道过滤器

管道也可以作为过滤器来使用,例如过滤一个list中的元素,将符合条件的元素返回出来

先写入以下:

app.component.ts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import { Component, OnInit, OnChanges } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{
  strList: string[] = [];

  addString(str: string){
    this.strList.push(str);
  }
}

app.component.html:

1
2
3
4
<input type="text" #box (keyup.enter)="addString(box.value); box.value=''" placeholder="enter string">
<div *ngFor="let str of strList">
{{ str }}
</div>

以上的代码会在输入框按下enter后,将输入的内容添加到strList中,然后div就会自动显示

然后新建一个管道:

string-length-pipe.ts:

1
2
3
4
5
6
7
8
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'stringLength'})
export class StringLengthPipe implements PipeTransform {
  transform(value: string[]): string[] {
    return value.filter(str => str.length >= 5);
  }
}

这个管道会将输入的string数组中长度大于等于5的数据返回出来

  • "str => str.length >= 5"是一个lambada表达式,先定义了一个str参数,然后将满足条件(str.length >= 5)的参数返回出来

别忘了在app.module.ts中添加引用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { birthdayFormatPipe } from './birthday-format-pipe';
import { StringLengthPipe } from './string-length-pipe';    //添加引用

@NgModule({
  declarations: [
    AppComponent,
    birthdayFormatPipe,
    StringLengthPipe    //添加引用
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

然后在html中添加管道:

app.component.html:

1
2
3
4
<input type="text" #box (keyup.enter)="addString(box.value); box.value=''" placeholder="enter string">
<div *ngFor="let str of strList | stringLength">
{{ str }}
</div>

运行之后发现无论怎样都没反应,这是因为添加数据使用了push()方法
angular会认为strList始终是同一个数组,并没有发生变化,所以不会更新数据
我们需要把addString改为如下:

1
2
3
4
5
6
  addString(str: string){
    var tmpList: string[] = [];
    this.strList.forEach(ele => tmpList.push(ele));
    tmpList.push(str);
    this.strList = tmpList;
  }

这样每次添加数据都相当于是一个新的数组了,这个时候运行程序会发现只有长度大于等于5的数据会被显示出来:

pipe4