创建了一个 “重学TypeScript” 的微信群,想加群的小伙伴,加我微信 “semlinker”,备注 “1” 。阿里、京东、腾讯的大佬都在群里等你哟。
semlinker/awesome-typescript 1.6K
本文将使用 UltimateAngular/angular-pro-src 中的示例,来一步步介绍自定义管道的相关知识。在该示例中,我们将定义一个 FileSizePipe
管道,它用于实现对文件大小进行格式化显示。
切回正题,我们先来看一下数据:
1 2 3 4 5
| [ { name: 'logo.svg', size: 2120109, type: 'image/svg' }, { name: 'banner.jpg', size: 18029, type: 'image/jpg' }, { name: 'background.png', size: 1784562, type: 'image/png' } ];
|
上面数组中每一项表示一个文件信息,含有以下字段:
- name —— 文件名称
- size —— 文件大小(字节)
- type —— 文件类型
接下来我们需要实现的功能,是在显示文件信息时,把字节(Byte)转换为兆(MB)。要实现此功能,我们可以利用 Angular 的管道。在 Angular 中自定义管道,需要按照以下步骤:
- 使用 @Pipe 装饰器定义 Pipe 的 Metadata 信息,如 Pipe 的名称 —— name 属性。
- 实现 PipeTransform 接口中定义的 transform 方法。
现在我们来新建一个 filesize.pipe.ts
文件,然后定义一个 FileSizePipe 类,该实现实现了 PipeTransform 接口,具体如下:
1 2 3 4 5 6 7 8 9 10
| import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'filesize' }) export class FilesizePipe implements PipeTransform { transform(value: any, args?: any): any { return null; } }
|
字节与兆的转换规则:
1
| 1 MB = 1024 KB = 1024 * 1024 B
|
因此按照以上的转换规则,我们可以很容易把字节(Byte)转换为 兆(MB),需要注意的是要处理小数位,这里我们只保留两位小数:
1 2 3 4 5 6 7 8 9 10
| import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'filesize' }) export class FileSizePipe implements PipeTransform { transform(size: number, extension: string = 'MB') { return (size / (1024 * 1024)).toFixed(2) + extension; } }
|
定义完 FileSizePipe 管道,我们就可以直接在模板上使用它了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import { Component, OnInit } from '@angular/core';
interface File { name: string, size: any, type: string }
@Component({ selector: 'my-app', template: ` <div> <div *ngFor="let file of files"> <p>{{ file.name }}</p> <p>{{ file.size | filesize }}</p> </div> </div> ` }) export class AppComponent implements OnInit { files: File[]; ngOnInit() { this.files = [ { name: 'logo.svg', size: 2120109, type: 'image/svg' }, { name: 'banner.jpg', size: 18029, type: 'image/jpg' }, { name: 'background.png', size: 1784562, type: 'image/png' } ]; } }
|
需要注意的是与 AngularJS 1.x 的 Filter 一样,Angular 管道也支持参数和管道链。其实,要实现上述的功能,除了在页面模板中使用管道之外,我们也可以在页面渲染前,对数据源进行处理。
前面我们已经在 FileSizePipe 类中定义了 transform
方法,用于实现文件大小进行格式处理。那么现在问题来了,我们可以直接利用 FileSizePipe 对象提供的 transform
方法,来对数据源进行处理么?答案是可以的。
下面我们来介绍在组件类中,如何使用管道服务:
- 配置 Provider:
1 2 3 4 5 6 7 8 9
| import { FilesizePipe } from './filesize.pipe';
@Component({ selector: 'my-app', template: `...`, providers: [ FilesizePipe ] })
|
- 注入 FileSizePipe 管道服务:
1 2 3
| constructor( private fileSizePipe: FileSizePipe ) {}
|
- 数据处理
1 2 3 4 5 6 7 8 9 10 11
| mapped: File[];
ngOnInit() { this.mapped = this.files.map(file => { return { name: file.name, type: file.type, size: this.fileSizePipe.transform(file.size, 'MB') }; }); }
|
- 数据展示
1 2 3 4 5 6
| <div> <div *ngFor="let file of mapped"> <p>{{ file.name }}</p> <p>{{ file.size }}</p> </div> </div>
|
最终完整的示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import { Component, OnInit } from '@angular/core'; import { FileSizePipe } from './filesize.pipe';
interface File { name: string, size: any, type: string }
@Component({ selector: 'my-app', template: ` <h3>模板使用管道</h3> <div> <div *ngFor="let file of files"> <p>{{ file.name }}</p> <p>{{ file.size | filesize }}</p> </div> </div> <h3>组件类中使用管道</h3> <div> <div *ngFor="let file of mapped"> <p>{{ file.name }}</p> <p>{{ file.size }}</p> </div> </div> `, providers: [ FileSizePipe ] }) export class AppComponent implements OnInit { files: File[]; mapped: File[];
constructor( private fileSizePipe: FileSizePipe ) {} ngOnInit() { this.files = [ { name: 'logo.svg', size: 2120109, type: 'image/svg' }, { name: 'banner.jpg', size: 18029, type: 'image/jpg' }, { name: 'background.png', size: 1784562, type: 'image/png' } ];
this.mapped = this.files.map(file => { return { name: file.name, type: file.type, size: this.fileSizePipe.transform(file.size, 'MB') }; }); } }
|
有兴趣的同学,也可以直接浏览线上的示例 —— angular-filesize-pipe。
欢迎小伙伴们订阅全栈修仙之路,及时阅读 TypeScript、Node/Deno、Angular 技术栈最新文章。