angular2-管道

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了angular2-管道相关的知识,希望对你有一定的参考价值。

管道:

管道把数据作为输入,然后转换它,给出期望的输出。 我们将把组件的birthday属性转换成对人类更友好的日期格式,来说明这一点

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

插值表达式中,我们让组件的birthday值通过管道操作符( | )流动到 右侧的Date管道函数中。所有管道都会用这种方式工作。

 

内置管道:

Angular内置了一些管道,比如DatePipeUpperCasePipeLowerCasePipeCurrencyPipePercentPipe。 它们全都可以直接用在任何模板中。

要学习更多内置管道的知识,参见API参考手册,并用“pipe”为关键词对结果进行过滤。

 

对管道进行参数化

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

 

我们将通过修改生日模板来给这个日期管道提供一个格式化参数。 当格式化完该英雄的4月15日生日之后,它应该被渲染成04/15/88

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

 

参数值可以是任何有效的模板表达式(参见模板语法中的模板表达式部分),比如字符串字面量或组件的属性。 换句话说,借助属性绑定,我们也可以像用绑定来控制生日的值一样,控制生日的显示格式。

<p>The hero‘s birthday is {{ birthday | date:format }}</p>

 

链式管道: {{ birthday | date | uppercase}}

 

自定义管道:

我们还可以写自己的自定义管道。 下面就是一个名叫ExponentialStrengthPipe的管道,它可以放大英雄的能力:

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

@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方法。

 

要注意的有两点:

    • 我们使用自定义管道的方式和内置管道完全相同。

    • 我们必须在AppModuledeclarations数组中包含这个管道。

 

纯(pure)管道与非纯(impure)管道

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

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

纯管道:

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

Angular会忽略(复合)对象内部的更改。 如果我们更改了输入日期(Date)中的月份、往一个输入数组(Array)中添加新值或者更新了一个输入对象(Object)的属性,Angular都不会调用纯管道。

非纯管道:

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

要在脑子里绷着这根弦,我们必须小心翼翼的实现非纯管道。 一个昂贵、迟钝的管道将摧毁用户体验。

 

我们把FlyingHeroesPipe换成了FlyingHeroesImpurePipe。 下面是完整的实现:

 

@Pipe({
  name: ‘flyingHeroesImpure‘,
  pure: false
})
export class FlyingHeroesImpurePipe extends FlyingHeroesPipe {}

  我们把它从FlyingHeroesPipe中继承下来,以证明无需改动内部代码。 唯一的区别是管道元数据中的pure标志。

 

非纯 AsyncPipe

Angular的AsyncPipe是一个有趣的非纯管道的例子。 AsyncPipe接受一个PromiseObservable作为输入,并且自动订阅这个输入,最终返回它们给出的值。

AsyncPipe管道是有状态的。 该管道维护着一个所输入的Observable的订阅,并且持续从那个Observable中发出新到的值。

 

没有FilterPipe或者OrderByPipe

 熟悉AngularJS的开发人员应该知道filterorderBy过滤器,但在Angular中它们没有等价物。

这并不是疏忽。Angular不想提供这些管道,因为 (a) 它们性能堪忧,以及 (b) 它们会阻止比较激进的代码最小化(minification)。 无论是filter还是orderBy都需要它的参数引用对象型属性。 我们前面学过,这样的管道必然是非纯管道,并且Angular会在几乎每一次变更检测周期中调用非纯管道

我们使用文本字符串来标记出排序字段,期望管道通过索引形式(如hero[‘name‘])引用属性的值。 不幸的是,激进的代码最小化策略会改变Hero类的属性名,所以Hero.nameHero.planet可能会被变成Hero.aHero.b。 显然,hero[‘name‘]是无法正常工作的。

 

Angular开发组和一些有经验的Angular开发者强烈建议你:把你的过滤和排序逻辑挪进组件本身。 组件可以对外暴露一个filteredHeroessortedHeroes属性,这样它就获得控制权,以决定要用什么频度去执行其它辅助逻辑。 你原本准备实现为管道,并在整个应用中共享的那些功能,都能被改写为一个过滤/排序的服务,并注入到组件中。

 

如果你不需要顾虑这些性能和最小化问题,也可以创建自己的管道来实现这些功能(参考FlyingHeroesPipe中的写法)或到社区中去找找

 

 

 

 

以上是关于angular2-管道的主要内容,如果未能解决你的问题,请参考以下文章

Angular2-管道

Angular2:找不到自定义管道

angular2-管道

Angular2:使用管道动态渲染模板

markdown Angular2 Snippets - 管道

typescript Angular2文本突出显示管道