AngularJs 1.x 中使用 filters 来帮助我们转换templates中的输出,但在Angular2中使用的是 pipes ,以下展示Angular 1.x and Angular 2中filter和pipe的对比:
| currency | ✓ | ✓ |
| date | ✓ | ✓ |
| uppercase | ✓ | ✓ |
| json | ✓ | ✓ |
| limitTo | ✓ | ✓ |
| lowercase | ✓ | ✓ |
| number | ✓ | |
| orderBy | ✓ | |
| filter | ✓ | |
| async | ✓ | |
| decimal | ✓ | |
| percent | ✓ |
Basic Pipes
// app.ts
// <reference path="typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap} from 'angular2/angular2' ;
@Component({
selector: 'pipes'
})
@View({
templateUrl: 'pipesTemplate.html'
})
// Component controller
class PipesAppComponent {
date: Date;
constructor() {
this .date = new Date();
}
}
bootstrap(PipesAppComponent);
<!-- pipesTemplate.html -->
<h1>Dates</h1>
<!-- Sep 1, 2015 -->
<p>{{date | date:'mediumDate'}}</p>
<!-- September 1, 2015 -->
<p>{{date | date:'yMMMMd'}}</p>
<!-- 3:50 pm -->
<p>{{date | date:'shortTime'}}</p>
结果:
New Pipes
decimal和percent是Angular2中新增的管道,参数规则是: {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits} .
decimal管道在模板中使用number关键字
// app.ts
...
@View({
templateUrl: 'pipesTemplate.html'
})
class PipesAppComponent {
grade: number;
rating: number;
constructor() {
this .grade = 0.99 ;
this .rating = 9.1243 ;
}
}
...
html
<h1>Decimals/Percentages</h1>
<!-- 99.00% -->
<p>{{grade | percent:'.2'}}</p>
<!-- 09.12 -->
<p>{{rating | number:'2.1-2'}}</p>
结果:
Async Pipe
Angular 2's async allows us to bind our templates directly to values that arrive asynchronously. This ability is great for working with promises and observables.
// app.ts
...
@Component({
selector: 'pipes' ,
changeDetection: 'ON_PUSH'
})
@View({
templateUrl: 'pipesTemplate.html' ,
})
class PipesAppComponent {
promise: Promise;
constructor() {
this .promise = new Promise( function (resolve, reject) {
setTimeout( function () {
resolve( "Hey, I'm from a promise." );
}, 2000 )
});
}
}
...
html
<!-- pipesTemplate.html -->
<h1>Async</h1>
<p>{{ promise | async}}</p>
After a 2 second delay, the value from the resolved promise will be displayed on the screen.
Custom Pipes
自定义pipe需要使用@Pipe装饰器,并实现PipeTransform接口里的transform方法。定义好的pipe要在需使用pipe的view或component中声明。
Pipe接口的定义
export interface Pipe {
name: string;
pure ?: boolean ;
}
PipeDecorator
export const Pipe: PipeDecorator = <PipeDecorator>makeDecorator('Pipe' , {
name: undefined,
pure: true , // 默认是pure
});
PipeTransform接口
export interface PipeTransform {
transform(value: any, ...args: any[]): any;
}
管道分类
pure 管道:仅当管道输入值变化的时候,才执行转换操作,默认的类型是 pure 类型。(备注:输入值变化是指原始数据类型如:string、number、boolean 等的数值或对象的引用值发生变化)
impure 管道:在每次变化检测期间都会执行,如鼠标点击或移动都会执行 impure 管道
// app.ts
import {Component, View, bootstrap, Pipe, PipeTransform} from 'angular2/angular2' ;
...
// We use the @Pipe decorator to register the name of the pipe
@Pipe({
name: 'tempConvert'
})
// The work of the pipe is handled in the tranform method with our pipe's class
class TempConvertPipe implements PipeTransform {
transform(value: number, args: any[]) {
if (value && !isNaN(value) && args[0] === 'celsius' ) {
var temp = (value - 32) * 5/9;
var places = args[1 ];
return temp.toFixed(places) + ' C' ;
}
return ;
}
}
...
@View({
templateUrl: 'pipesTemplate.html' ,
// We can pass the pipe class name into the pipes key to make it usable in our views
pipes: [TempConvertPipe]
})
class PipesAppComponent {
temperature: number;
constructor() {
this .temperature = 85 ;
}
}
html
<h1>Custom Pipes - Convert Temperature</h1>
<!-- 85 F -->
<h3>Fahrenheit: {{temperature + ' F'}}</h3>
<!-- 29.4 C -->
<h3>Celsius: {{temperature | tempConvert:'celsius':1}}</h3>
结果
过滤出指定范围的值
定义一个pipe
import {Pipe, PipeTransform} from 'angular2/core' ;
// Tell Angular2 we're creating a Pipe with TypeScript decorators
@Pipe({
name: 'AgePipe'
})
export class AgePipe implements PipeTransform {
// Transform is the new "return function(value, args)" in Angular 1.x
transform(value, args? ) {
// ES6 array destructuring
let [minAge, maxAge] = args;
return input.filter(person => {
return person.age >= +minAge && person.age <= + maxAge;
});
}
}
import {Component} from 'angular2/core' ;
import {AgePipe} from './pipes/age-pipe/age-pipe' ;
@Component({
selector: 'playground-app' ,
templateUrl: 'app/playground.html' ,
// tell our component it uses our AgePipe
pipes: [AgePipe]
})
export class PlaygroundApp {
sliderValue:number = 20 ;
anotherSliderValue: number = 90 ;
people:Array <any> = [{
name: 'Justin Bieber' ,
age: 21
}, {
name: 'Miley Cyrus' ,
age: 23
}, {
name: 'John Legend' ,
age: 37
}, {
name: 'Betty White' ,
age: 94
}, {
name: 'Roger Waters' ,
age: 72
}, {
name: 'Larry Page' ,
age: 42
}];
}
html
<div>
<p>
0
<input type="range" min="0" max="100"
[value] ="sliderValue"
(input) ="sliderValue = $event.target.value" />
100
</p>
<span>{{ sliderValue }}</span>
<p>
0
<input type="range" min="0" max="100"
[(ngModel)] ="anotherSliderValue" />
100
</p>
<span>{{anotherSliderValue }}</span>
<ul>
<li *ngFor="#person of people | AgePipe:sliderValue:anotherSliderValue">
{{ person.name }} ({{ person.age }})
</li>
</ul>
</div>