Angular2 - 管道

管道的作用:

  管道把数据作为输入,然后转换它,给出期望的输出可以有好的将“显示--值”转换器 声明在HTML中。

管道表达式:  {{ 显示 | 格式 }}

使用管道:

<p>The hero's birthday is {{ birthday | date }}</p>

内置的管道:

  比如 DatePipeUpperCasePipeLowerCasePipeCurrencyPipe 和 PercentPipe。 它们全都可以直接用在任何模板中

对管道进行参数化:

  管道可能接受任何数量的可选参数来对它的输出进行微调。 可以在管道名后面添加一个冒号( : )再跟一个参数值,来为管道添加参数(比如 currency:'EUR')。 如果这个管道可以接受多个参数,那么就用冒号来分隔这些参数值(比如 slice:1:5)。

<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>

 

  还可以将管道的格式参数绑定到该组件的属性上:如下所示

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; }
}

链式管道:把管道串联在一起,以组合出一些潜在的有用功能。

 

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)管道与非纯(impure)管道

  有两类管道:纯的与非纯的。 默认情况下,管道都是纯的。以前见到的每个管道都是纯的。 通过把它的 pure 标志设置为 false,你可以制作一个非纯管道。你可以像这样让 FlyingHeroesPipe 变成非纯的:

@Pipe({
  name: 'flyingHeroesImpure',
  pure: false
})

纯管道:

  Angular 只有在它检测到输入值发生了纯变更时才会执行纯管道。 纯变更是指对原始类型值(StringNumberBooleanSymbol)的更改, 或者对对象引用(DateArrayFunctionObject)的更改。

非纯管道

  Angular 会在每个组件的变更检测周期中执行非纯管道。 非纯管道可能会被调用很多次,和每个按键或每次鼠标移动一样频繁。

 

非纯 AsyncPipe

     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;
  }
}

 

 

 

 

 

posted @ 2018-09-19 09:53  猪快跑  阅读(477)  评论(0编辑  收藏  举报