标签:更新 放大 告诉 关键点 href 性能 区别 nts 知识
管道把数据作为输入,然后转换它,给出期望的输出。 我们将把组件的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>
我们还可以写自己的自定义管道。 下面就是一个名叫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
。
transform
方法是管道的基本要素。 PipeTransform
接口中定义了它,并用它指导各种工具和编译器。 理论上说,它是可选的。Angular不会管它,而是直接查找并执行transform
方法。
要注意的有两点:
我们使用自定义管道的方式和内置管道完全相同。
我们必须在AppModule
的declarations
数组中包含这个管道。
有两类管道:纯的与非纯的。 默认情况下,管道都是纯的。我们以前见到的每个管道都是纯的。 通过把它的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
标志。
Angular的AsyncPipe
是一个有趣的非纯管道的例子。 AsyncPipe
接受一个Promise
或Observable
作为输入,并且自动订阅这个输入,最终返回它们给出的值。
AsyncPipe
管道是有状态的。 该管道维护着一个所输入的Observable
的订阅,并且持续从那个Observable
中发出新到的值。
熟悉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中的写法)或到社区中去找找
标签:更新 放大 告诉 关键点 href 性能 区别 nts 知识
原文地址:http://www.cnblogs.com/vs1435/p/7794127.html