管道的做用:api
管道把數據做爲輸入,而後轉換它,給出指望的輸出。能夠有好的將「顯示--值」轉換器 聲明在HTML中。數組
管道表達式: {{ 顯示 | 格式 }}緩存
使用管道:服務器
<p>The hero's birthday is {{ birthday | date }}</p>
內置的管道:app
好比 DatePipe
、UpperCasePipe
、LowerCasePipe
、CurrencyPipe
和 PercentPipe
。 它們全均可以直接用在任何模板中async
對管道進行參數化:ide
管道可能接受任何數量的可選參數來對它的輸出進行微調。 能夠在管道名後面添加一個冒號( : )再跟一個參數值,來爲管道添加參數(好比 currency:'EUR'
)。 若是這個管道能夠接受多個參數,那麼就用冒號來分隔這些參數值(好比 slice:1:5
)。工具
<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>
還能夠將管道的格式參數綁定到該組件的屬性上:以下所示fetch
template: ` <p>The hero's birthday is {{ birthday | date:format }}</p> <button (click)="toggleFormat()">Toggle Format</button> `
export class HeroBirthday2Component { birthday = new Date(1988, 3, 15); // April 15, 1988 toggle = true; // start with true == shortDate get format() { return this.toggle ? 'shortDate' : 'fullDate'; } toggleFormat() { this.toggle = !this.toggle; } }
鏈式管道:把管道串聯在一塊兒,以組合出一些潛在的有用功能。ui
The chained hero's birthday is
{{ birthday | date | uppercase}}
//一樣的方式連接了這兩個管道,並且同時還給 date 管道傳進去一個參數
The chained hero's birthday is
{{ birthday | date:'fullDate' | uppercase}}
自定義管道:
import { Pipe, PipeTransform } from '@angular/core'; /* * Raise the value exponentially * Takes an exponent argument that defaults to 1. * Usage: * value | exponentialStrength:exponent * Example: * {{ 2 | exponentialStrength:10 }} * formats to: 1024 */ @Pipe({name: 'exponentialStrength'}) export class ExponentialStrengthPipe implements PipeTransform { transform(value: number, exponent: string): number { let exp = parseFloat(exponent); return Math.pow(value, isNaN(exp) ? 1 : exp); } }
在這個管道的定義中體現了幾個關鍵點:
管道是一個帶有「管道元數據(pipe metadata)」裝飾器的類。
這個管道類實現了 PipeTransform
接口的 transform
方法,該方法接受一個輸入值和一些可選參數,並返回轉換後的值。
當每一個輸入值被傳給 transform
方法時,還會帶上另外一個參數,好比你這個管道就有一個 exponent
(放大指數) 參數。
能夠經過 @Pipe
裝飾器來告訴 Angular:這是一個管道。該裝飾器是從 Angular 的 core
庫中引入的。
這個 @Pipe
裝飾器容許你定義管道的名字,這個名字會被用在模板表達式中。它必須是一個有效的 JavaScript 標識符。 好比,你這個管道的名字是 exponentialStrength
。
PipeTransform 接口
transform 方法是管道的基本要素。 PipeTransform接口中定義了它,並用它指導各類工具和編譯器。
理論上說,它是可選的。Angular 不會管它,而是直接查找並執行 transform 方法。
請注意如下幾點:
你使用自定義管道的方式和內置管道徹底相同。
你必須在 AppModule
的 declarations
數組中包含這個管道
有兩類管道:純的與非純的。 默認狀況下,管道都是純的。之前見到的每一個管道都是純的。 經過把它的 pure
標誌設置爲 false
,你能夠製做一個非純管道。你能夠像這樣讓 FlyingHeroesPipe
變成非純的:
@Pipe({ name: 'flyingHeroesImpure', pure: false })
Angular 只有在它檢測到輸入值發生了純變動時纔會執行純管道。 純變動是指對原始類型值(String
、Number
、Boolean
、Symbol
)的更改, 或者對對象引用(Date
、Array
、Function
、Object
)的更改。
Angular 會在每一個組件的變動檢測週期中執行非純管道。 非純管道可能會被調用不少次,和每一個按鍵或每次鼠標移動同樣頻繁。
AsyncPipe
接受一個 Promise
或 Observable
做爲輸入,而且自動訂閱這個輸入,最終返回它們給出的值。
AsyncPipe
管道是有狀態的。 該管道維護着一個所輸入的 Observable
的訂閱,而且持續從那個 Observable
中發出新到的值。
下面例子使用該 async
管道把一個消息字符串(message$
)的 Observable
綁定到視圖中:
import { Component } from '@angular/core'; import { Observable, interval } from 'rxjs'; import { map, take } from 'rxjs/operators'; @Component({ selector: 'app-hero-message', template: ` <h2>Async Hero Message and AsyncPipe</h2> <p>Message: {{ message$ | async }}</p> <button (click)="resend()">Resend</button>`, }) export class HeroAsyncMessageComponent { message$: Observable<string>; private messages = [ 'You are my hero!', 'You are the best hero!', 'Will you be my hero?' ]; constructor() { this.resend(); } resend() { this.message$ = interval(500).pipe( map(i => this.messages[i]), take(this.messages.length) ); } }
來寫更多的非純管道:一個向服務器發起 HTTP 請求的管道。
時刻記住,非純管道可能每隔幾微秒就會被調用一次。 若是你不當心點,這個管道就會發起一大堆請求「攻擊」服務器。
下面這個管道只有當所請求的 URL 發生變化時纔會向服務器發起請求。它會緩存服務器的響應。 代碼以下,它使用Angular http客戶端來接收數據。
import { Pipe, PipeTransform } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Pipe({ name: 'fetch', pure: false }) export class FetchJsonPipe implements PipeTransform { private cachedData: any = null; private cachedUrl = ''; constructor(private http: HttpClient) { } transform(url: string): any { if (url !== this.cachedUrl) { this.cachedData = null; this.cachedUrl = url; this.http.get(url).subscribe( result => this.cachedData = result ); } return this.cachedData; } }