有狀態的管道

Angular 2 提供兩種不同型別的管道 - 無狀態和有狀態。管道預設是無狀態的。但是,我們可以通過將 pure 屬性設定為 false 來實現有狀態管道。正如你在引數部分中看到的,你可以指定 name 並宣告管道是否應該是純的,意味著有狀態或無狀態。當資料流經無狀態管道(這是一個純函式)時,它不記得任何東西,資料可以通過有狀態管道進行管理和記憶。有狀態管道的一個很好的例子是由 Angular 2 提供的 AsyncPipe

重要

請注意,大多數管道應屬於無狀態管道類別。這對於效能原因很重要,因為 Angular 可以為變化檢測器優化無狀態管道。所以謹慎使用有狀態管道。通常,Angular 2 中管道的優化與 Angular 1.x 中的過濾器相比具有顯著的效能提升。在 Angular 1 中,即使資料根本沒有改變,摘要週期也必須重新執行所有過濾器。在 Angular 2 中,一旦計算出管道的值,變更檢測器就知道不再執行該管道,除非輸入發生變化。

實施有狀態管道

import {Pipe, PipeTransform, OnDestroy} from '@angular/core';

@Pipe({
  name: 'countdown',
  pure: false
})
export class CountdownPipe implements PipeTransform, OnDestroy  {
  private interval: any;
  private remainingTime: number;

  transform(value: number, interval: number = 1000): number {
    if (!parseInt(value, 10)) {
      return null;
    }
    
    if (typeof this.remainingTime !== 'number') {
      this.remainingTime = parseInt(value, 10);
    }
    
    if (!this.interval) {
      this.interval = setInterval(() => {
        this.remainingTime--;
        
        if (this.remainingTime <= 0) {
          this.remainingTime = 0;
          clearInterval(this.interval);
          delete this.interval;
        }
      }, interval);
    }
    
    return this.remainingTime;
  }
  
  ngOnDestroy(): void {
    if (this.interval) {
      clearInterval(this.interval);
    }
  }
}

然後你可以照常使用管道:

{{ 1000 | countdown:50 }}
{{ 300 | countdown }}

重要的是你的管道也實現了 OnDestroy 介面,這樣你就可以在管道被破壞後進行清理。在上面的示例中,有必要清除間隔以避免記憶體洩漏。