Angular 2 Pipe vs Angular 1 Filter
一直想写关于 Angular 1.x 与 Angular 2.x (Angular 4.x 已发布) 区别的文章,方便 Angular 1.x 的用户快速的过渡到 Angular 2.x。在浏览文章的时候,发现 Todd Motto 大神,已经写了相关的系列文章。英文好的同学,建议直接阅读 Creating a custom filter (pipe) in Angular 原文哈,因为我并不打算完整地翻译。废话不多说,接下来我们开始进入正题。 目录
Angular 1.x首先我们先来介绍一下,自定义过滤器要实现的功能,即要对以下模板中 <!-- template code --> <p>You came {{ '1' }}</p> <p>You came {{ '2' }}</p> 格式化为: <!-- when compiled --> <p>You came 1st</p> <p>You came 2nd</p> 了解完需求后,接下来我们开始来实现该功能。 Creating a custom filter在 Angular 1.x 中,我们通过 const ordinal = () => { return value => { var suffix = ''; // 后缀名 var last = value % 10; var specialLast = value % 100; if (!value || value < 1) { return value; } if (last === 1 && specialLast !== 11) { suffix = 'st'; } else if (last === 2 && specialLast !== 12) { suffix = 'nd'; } else if (last === 3 && specialLast !== 13) { suffix = 'rd'; } else { suffix = 'th'; } return value + suffix; }; }; angular .module('app') // 获取已创建的app模块 .filter('ordinal',ordinal); // 使用filter API创建ordinal过滤器 Using filters in templateconst app = { template: ` <div> <ul> <li ng-repeat="num in $ctrl.numbers"> {{ num | ordinal }} </li> </ul> </div> `,controller() { this.numbers = [ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 ]; } }; angular .module('app') .component('app',app); 以上代码运行后的结果 - Plunker Passing arguments to filters为了让我们的 ordinal 过滤器更加灵活,它应该可以根据用户设置的参数,来动态的显示内容。接下来我们来看一下,Angular 1.x 中如何传递参数给过滤器。 const ordinal = () => { // passing another argument return (value,anotherValue) => { // do something with `value` and `anotherValue` // and return a new value }; }; angular .module('app') .filter('ordinal',ordinal); 更新后的 app 组件,如下: const app = { template: ` <div> <input ng-model="searchValue"> <ul> <li ng-repeat="num in $ctrl.numbers"> {{ num | ordinal:searchValue }} </li> </ul> </div> `,... }; Filtering in Controllers with $filter()除了在模板中使用 const app = { template: ` <div> <ul> <li ng-repeat="num in $ctrl.numbers"> {{ num }} </li> </ul> </div> `,controller($filter) { let numbers = [ 1,20 ]; // iterate the existing collection before binding // returns a new filtered collection this.numbers = numbers.map(number => $filter('ordinal')(number)); } }; Angular 2在 Angular 2 中,已经没有了 Creating a custom pipeordinal.pipe.ts import { Pipe,PipeTransform } from '@angular/core'; @Pipe({ name: 'ordinal' }) export class OrdinalPipe implements PipeTransform { transform(value: number): string { let suffix = ''; let last = value % 10; let specialLast = value % 100; if (!value || value < 1) { return '' + value; } if (last === 1 && specialLast !== 11) { suffix = 'st'; } else if (last === 2 && specialLast !== 12) { suffix = 'nd'; } else if (last === 3 && specialLast !== 13) { suffix = 'rd'; } else { suffix = 'th'; } return value + suffix; } } 通过以上示例,我们来总结一下自定义管道的步骤。自定义管道分为两个步骤:
Using pipes in template为了能够在组件中使用已创建的 app.component.ts import { Component } from '@angular/core'; @Component({ selector: 'exe-app',template: ` <div> <ul> <li *ngFor="let num of numbers"> {{ num | ordinal }} </li> </ul> </div> ` }) export class AppComponent { numbers: Array<number>; constructor() { this.numbers = [ 1,20 ]; } } app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { OrdinalPipe } from './ordinal.pipe'; @NgModule({ imports: [BrowserModule],declarations: [AppComponent,OrdinalPipe],bootstrap: [AppComponent] }) export class AppModule { } Passing arguments to pipes在 Angular 2 中,我们也可以为管道添加参数,具体示例如下: import { Pipe,PipeTransform } from '@angular/core'; @Pipe({ name: 'ordinal' }) export class OrdinalPipe implements PipeTransform { // passing another argument transform(value: number,anotherValue: string): string { // do something with `value` and `anotherValue` // and return a new value } } Filtering in Component classes with pipes在 Angular 1.x 中,我们推荐在 Controller 中使用 import { Component } from '@angular/core'; import { OrdinalPipe } from './ordinal.pipe'; @Component({ selector: 'exe-app',template: ` <div> <ul> <li *ngFor="let num of numbers"> {{ num }} </li> </ul> </div> `,providers: [OrdinalPipe] }) export class AppComponent { numbers: Array<string>; constructor(private pipe: OrdinalPipe) { let numbers = [ 1,20 ]; this.numbers = numbers.map(number => this.pipe.transform(number)); } } 以上示例为了能够通过构造注入的方式,注入 OrdinalPipe 管道实例,我们必须在组件的 metadata 信息中,定义 providers 属性。 我有话说1.Angular 2 中要掌握管道,还需要了解哪些知识点? 要全面掌握 Angular 2 中的管道,你还需了解以下内容:
详细内容请参考 - Angular 2 Pipe 2.在组件类中注入管道实例,如果没有在组件的 metadata 信息中,定义 providers 属性会出现什么问题?(该问题,初学者可以先略过哈) 在回答这个问题之前,我们先来看一下未设置 providers 属性和已设置 providers 属性,编译后的代码: 未设置 providers 属性 : View_AppComponent_Host0.prototype.injectorGetInternal = // 注入器获取内部依赖项 function(token,requestNodeIndex,notFoundResult) { var self = this; if (((token === jit_AppComponent1) && (0 === requestNodeIndex))) { return self._AppComponent_0_3.context; } return notFoundResult; }; 已设置 providers 属性 : View_AppComponent_Host0.prototype.injectorGetInternal = // 注入器获取内部依赖项 function(token,notFoundResult) { var self = this; if (((token === jit_OrdinalPipe1) && (0 === requestNodeIndex))) { return self._OrdinalPipe_0_3; } if (((token === jit_AppComponent2) && (0 === requestNodeIndex))) { return self._AppComponent_0_4.context; } return notFoundResult; }; 我们再来看一下未设置 providers 属性 时,控制台的输出结果:
为什么提示 No provider for OrdinalPipe,相信你已经知道了答案了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |