angular2-管道
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了angular2-管道相关的知识,希望对你有一定的参考价值。
管道:
管道把数据作为输入,然后转换它,给出期望的输出。 我们将把组件的birthday
属性转换成对人类更友好的日期格式,来说明这一点
<p>The hero‘s birthday is {{ birthday | date }}</p>
插值表达式中,我们让组件的birthday
值通过管道操作符( | )流动到 右侧的Date管道函数中。所有管道都会用这种方式工作。
内置管道:
Angular内置了一些管道,比如DatePipe
、UpperCasePipe
、LowerCasePipe
、CurrencyPipe
和PercentPipe
。 它们全都可以直接用在任何模板中。
要学习更多内置管道的知识,参见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
方法。
要注意的有两点:
-
-
我们使用自定义管道的方式和内置管道完全相同。
-
我们必须在
AppModule
的declarations
数组中包含这个管道。
-
纯(pure)管道与非纯(impure)管道
有两类管道:纯的与非纯的。 默认情况下,管道都是纯的。我们以前见到的每个管道都是纯的。 通过把它的pure
标志设置为false
,我们可以制作一个非纯管道。我们可以像这样让FlyingHeroesPipe
变成非纯的
@Pipe({ name: ‘flyingHeroesImpure‘, pure: false })
纯管道:
Angular只有在它检测到输入值发生了纯变更时才会执行纯管道。 纯变更是指对原始类型值(String
、Number
、Boolean
、Symbol
)的更改, 或者对对象引用(Date
、Array
、Function
、Object
)的更改。
Angular会忽略(复合)对象内部的更改。 如果我们更改了输入日期(Date
)中的月份、往一个输入数组(Array
)中添加新值或者更新了一个输入对象(Object
)的属性,Angular都不会调用纯管道。
非纯管道:
Angular会在每个组件的变更检测周期中执行非纯管道。 非纯管道可能会被调用很多次,和每个按键或每次鼠标移动一样频繁。
要在脑子里绷着这根弦,我们必须小心翼翼的实现非纯管道。 一个昂贵、迟钝的管道将摧毁用户体验。
我们把FlyingHeroesPipe
换成了FlyingHeroesImpurePipe
。 下面是完整的实现:
@Pipe({
name: ‘flyingHeroesImpure‘,
pure: false
})
export class FlyingHeroesImpurePipe extends FlyingHeroesPipe {}
我们把它从FlyingHeroesPipe
中继承下来,以证明无需改动内部代码。 唯一的区别是管道元数据中的pure
标志。
非纯 AsyncPipe
Angular的AsyncPipe
是一个有趣的非纯管道的例子。 AsyncPipe
接受一个Promise
或Observable
作为输入,并且自动订阅这个输入,最终返回它们给出的值。
AsyncPipe
管道是有状态的。 该管道维护着一个所输入的Observable
的订阅,并且持续从那个Observable
中发出新到的值。
没有FilterPipe或者OrderByPipe
熟悉AngularJS的开发人员应该知道filter
和orderBy
过滤器,但在Angular中它们没有等价物。
这并不是疏忽。Angular不想提供这些管道,因为 (a) 它们性能堪忧,以及 (b) 它们会阻止比较激进的代码最小化(minification)。 无论是filter
还是orderBy
都需要它的参数引用对象型属性。 我们前面学过,这样的管道必然是非纯管道,并且Angular会在几乎每一次变更检测周期中调用非纯管道
我们使用文本字符串来标记出排序字段,期望管道通过索引形式(如hero[‘name‘]
)引用属性的值。 不幸的是,激进的代码最小化策略会改变Hero
类的属性名,所以Hero.name
和Hero.planet
可能会被变成Hero.a
和Hero.b
。 显然,hero[‘name‘]
是无法正常工作的。
Angular开发组和一些有经验的Angular开发者强烈建议你:把你的过滤和排序逻辑挪进组件本身。 组件可以对外暴露一个filteredHeroes
或sortedHeroes
属性,这样它就获得控制权,以决定要用什么频度去执行其它辅助逻辑。 你原本准备实现为管道,并在整个应用中共享的那些功能,都能被改写为一个过滤/排序的服务,并注入到组件中。
如果你不需要顾虑这些性能和最小化问题,也可以创建自己的管道来实现这些功能(参考FlyingHeroesPipe中的写法)或到社区中去找找
以上是关于angular2-管道的主要内容,如果未能解决你的问题,请参考以下文章