管道是一些对数据进行转换和格式化的函数。
使用管道也非常简单,只需要引入管道操作符( | )即可。管道操作符会把左侧的变量或表达式的值传给右侧的管道函数,并返回一个转换后的值。
Angular 内置了一些常用的管道:
date:根据本地环境中的规则格式化日期值。
例子:
// html <p>{{ birthday | date:'short' }}</p> <!-- 输出: 9/20/21, 3:22 PM --> <p>{{ birthday | date:'medium' }}</p> <!-- 输出: Sep 20, 2021, 3:22:11 PM --> <p>{{ birthday | date:'long' }}</p> <!-- 输出: September 20, 2021 at 3:22:11 PM GMT+8 --> <p>{{ birthday | date:'full' }}</p> <!-- 输出: Monday, September 20, 2021 at 3:22:11 PM GMT+08:00 --> <p>{{ birthday | date:'shortDate' }}</p> <!-- 输出: 9/20/21 --> <p>{{ birthday | date:'mediumDate' }}</p> <!-- 输出: Sep 20, 2021 --> <p>{{ birthday | date:'longDate' }}</p> <!-- 输出: September 20, 2021 --> <p>{{ birthday | date:'fullDate' }}</p> <!-- 输出: Monday, September 20, 2021 --> <p>{{ birthday | date:'shortTime' }}</p> <!-- 输出: 3:22 PM --> <p>{{ birthday | date:'mediumTime' }}</p> <!-- 输出: 3:22:11 PM --> <p>{{ birthday | date:'longTime' }}</p> <!-- 输出: 3:22:11 PM GMT+8 --> <p>{{ birthday | date:'fullTime' }}</p> <!-- 输出: 3:22:11 PM GMT+08:00 --> <p>{{ birthday | date:"yyyy/MM/dd" }}</p> <!-- 输出: 2021/09/22 --> <p>{{ birthday | date:"h:mm:ss" }}</p> <!-- 输出: 3:29:29 --> // ts birthday = new Date();
upperCase:把文本全部转换成大写。
lowerCase:把文本全部转换成小写。
例子:
// html <p>{{ text01 | uppercase }}</p> <!-- 输出: OUTPUT --> <p>{{ text02 | lowercase }}</p> <!-- 输出: input --> // ts text01 = 'output'; text02 = 'INPUT';
也可以对管道进行串联:
例子:
// html <p>{{ birthday | date | uppercase }}</p> <!-- 输出: SEP 22, 2021 --> // ts birthday = new Date();
创建管道
例子:
// 文件名:safeHtml.pipe.ts // 引入装饰器 Pipe 和接口 PipeTransform import { Pipe, PipeTransform } from '@angular/core'; // 定义管道名称 @Pipe({ name: 'safeHtml' }) // 实现 PipeTransform 接口中定义的 transform 方法 export class SafeHtmlPipe implements PipeTransform { // value:需要转换的值(即使用管道时,等号左侧的值) // args:处理 value 时的附带条件 transform(value: string, args?: number): string { if(!value) return value; const num = args || 5; return value.slice(0, num) + '......'; } }
使用自定义管道
和使用组件一样,首先在对应的模块中引入并声明管道。
例子:
// 文件名:app.module.ts import { NgModule } from '@angular/core'; import { FormsModule } from "@angular/forms"; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; // 引入 SafeHtmlPipe import { SafeHtmlPipe } from './components/safeHtml.pipe'; @NgModule({ declarations: [ AppComponent, // 声明 SafeHtmlPipe SafeHtmlPipe ], imports: [ BrowserModule, AppRoutingModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
然后,就可以在该模块下的所有组件中使用这个管道了。
例子:
// html <p>{{ text01 | safeHtml:3 }}</p> <!-- 输出:我是天...... --> <p>{{ text02 | safeHtml }}</p> <!-- 输出:偶尔投影在...... --> // ts text01 = '我是天空里的一片云'; text02 = '偶尔投影在你的波心';
默认情况下,当 Angular 检测到变量或表达式的值有变化时,就会调用管道函数。
当这个值是基本类型时(例如 String、Number、Boolean 等 ),管道可以正常执行,但是当这个值是引用类型时(比如 Array、Object 等),只有引用地址发生变化时,管道才可以正常执行。
例子:
// 文件名:welcome.pipe.ts import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'welcome' }) export class WelcomePipe implements PipeTransform { transform(value:string[]): Array<string> { if(!value) return []; return value.map((name:string)=>{ return 'hello '+name; }); } }
使用已经定义好的管道 welcome:
// html <p *ngFor="let name of (nameList | welcome)"> {{name}} </p> <button (click)="AddName()">AddName</button> // ts nameList = ['Tom', 'Mess', 'Amy']; AddName(){ this.nameList.push('Lili'); }
例子中,当我们点击 AddName 按钮时,并没有将’Lili’添加到页面上,原因就是数组的引用没有改变,所以 Angular 认为该数组仍是相同的,所以不会更新模板。那么,我们可以通过更改数组的引用来实现更新。
例子:
//ts nameList = ['Tom', 'Mess', 'Amy']; AddName(){ this.nameList = [...this.nameList,'Lili']; // this.nameList.push('Lili'); }
除了这个方法,我们也可以通过非纯管道来实现引用类型值的变更检测。 默认情况下,我们自定义的管道都是纯管道,可以通过把 pure 标志设置为 false,将纯管道设置成非纯管道:
@Pipe({ name: 'welcome', pure: false })
如此一来,引用类型值的内部变化也会调用管道函数。
例子:
// 文件名:welcome.pipe.ts import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'welcome', pure:false }) export class WelcomePipe implements PipeTransform { transform(value:string[]): Array<string> { if(!value) return []; return value.map((name:string)=>{ return 'hello '+name; }); } }
使用非纯管道 welcome:
// html <p *ngFor="let name of (nameList | welcome)"> {{name}} </p> <button (click)="AddName()">AddName</button> // ts nameList = ['Tom', 'Mess', 'Amy']; AddName(){ // this.nameList = [...this.nameList,'Lili']; this.nameList.push('Lili'); }
值得注意的是,这种非纯管道虽然方便简单,但是每一次的页面操作(按键或者鼠标移动、点击),Angular 都会执行一次非纯管道,从而导致应用的性能下降,造成卡顿的现象,因此要慎重使用。
end