有状态的管道

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 接口,这样你就可以在管道被破坏后进行清理。在上面的示例中,有必要清除间隔以避免内存泄漏。