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>