Angular 18+ 高级教程 – Component 组件 の Pipe 管道
介绍
Pipe 类似于 Template Syntax,它的用途是 transform value for display。
参考:
DatePipe
一个简单的例子。
我有一个 JavaScript 的 Date value,我要 display 给用户看,那你不可能直接 .toString() 就显示嘛,很丑丫。
所以呢,它就需要一个 transformation。而按照职责划分(Thinking in Angular Way),这个任务显然是属于 view 的 logic。
所以应该在 HTML 去表达。于是就有了 Pipe 写法。
<h1>{{ today }}</h1>
<h1>{{ today | date : 'dd MMM yyyy' }}</h1>
<h1>{{ today | date : 'fullDate' }}</h1>
pipe 的语法是这样的 {{ value | pipeName : paramter1 : paramter2 }}
你可以把它看作是一个 function call。
比如现在我们使用的 DatePipe,就是 const displayDate = date(today , 'dd MMM yyyy');
today 是 component property,是一个 new Date()
| pipe 就是启动 pipe transform。
date 是 Angular build-in 的 DatePipe,Angular build-in 了许多 pipe,每一个负责不同的 transform,顾名思义 DatePipe 自然是用于 transform date value。
注:要使用 Angular build-in 的 Pipe,必须在 Component metadata imports CommonModule 哦。
: 分号表示要输入 paramters
'dd MMM yyyy' 则是输入的 parameter,声明想 transform to 什么 date format。(p.s. 想知道所有 Angular 支持的 format, 参考这里)
效果

UpperCasePipe, LowerCasePipe, TitleCase
<h1>{{ 'Hello World' | uppercase }}</h1>
<h1>{{ 'Hello World' | lowercase }}</h1>
<h1>{{ 'hello world' | titlecase }}</h1>
效果

DecimalPipe
在 JavaScript, 我们可以用下划线来分割 number 让它好看一点
<h1>{{ 1_000_000 }}</h1>
但当渲染 HTML 的时候,它会被 number.toString(),结果变成

DecimalPipe 可用于解决这种问题。
<h1>{{ 1_000_000 | number }}</h1>
注:虽然它叫 DecimalPipe,但使用时是 | number 哦。
效果

除此之外,number 还支持一个 digit setting,
它可以控制小数点前后号码,最少最多几个数字。
语法是
{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}
for example '2.2-4' 表示小数点前最少要 2 digit,小数点后最少 2 最多 4 个 digit。
不够 digit 时它会用零补上,超过 digit 时它会四舍五入进位.
<h1>{{ 1.10 | number : '2.2-4' }}</h1> <!--01.10 前面补上了一个 0 -->
<h1>{{ 0.1 | number : '.2-4' }}</h1> <!--0.10 后面补上了一个 0-->
<h1>{{ .123 | number : '1.2-4' }}</h1> <!--0.123 前面补上了一个 0-->
<h1>{{ .12345 | number : '1.2-4' }}</h1> <!--0.1235 后面四舍五入进位-->
注:它的 default 是 '1.0-3'。另外,小数点前只能控制最少 digit,不能控制最多。
PercentPipe
PercentPipe 的作用时把 0.57 变成 '57%'
<h1>{{ 0.57 | percent }}</h1>
效果

它也支持 digit setting
<h1>{{ 0.575 | percent : '.0' }}</h1> <!--58%-->
p.s. '.0' 相等于 '1.0-0',best practice 是写完整的 '1.0-0'。
CurrencyPipe
CurrentPipe 会 transform number 变成带有 current code。
<h1>{{ 100 | currency : 'USD' }}</h1> <!-- $100.00 默认是显示 symbol 哦 -->
<h1>{{ 100 | currency : 'USD' : 'code' }}</h1> <!-- USD100.00 -->
<h1>{{ 100 | currency : 'USD' : 'symbol' }}</h1> <!-- $100.00 -->
<h1>{{ 100 | currency : 'MYR' : 'symbol-narrow' }}</h1> <!-- RM100.00 -->
<h1>{{ 100 | currency : 'MYR' : 'M$ ' }}</h1> <!-- M$100.00 -->
第一个参数是 currency code ISO 4217
第二个参数是 display mode,有好几个选择:
'code' 表示显示 currency code
'symbol' 表示显示符号就够了。Angular 会把 code 转成对应的 symbol,比如 USD -> $
'symbol-narrow' 也是显示 symbol 但是是 "narrow" 版,马来西亚的 symbol-narrow 是 'RM' Ringgit Malaysia 的缩写
'whatever string',如果 code, symbol, symbol-narrow 都不是你要的,那可以提供一个 string 作为 display。
第三个参数是 digit setting,默认是 '1.2-2'。
Global override default currency
default currency 是 USD,我们可以通过 Dependancy Injection 的方式提供一个全局 currency 替换掉 default currency。
import { DEFAULT_CURRENCY_CODE, type ApplicationConfig } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [{ provide: DEFAULT_CURRENCY_CODE, useValue: 'MYR' }],
};
JsonPipe, SlicePipe, AsyncPipe
其它 build-in pipes.
<h1>{{ { name: 'Derrick' } | json }}</h1> <!-- { "name": "Derrick" } -->
<h1>{{ ['a', 'b', 'c', 'd'] | slice : 1 : -1 }}</h1> <!-- ['b', 'c'] -->
<h1>{{ value$ | async }}</h1> <!-- value1---value2---value3 -->
async pipe 常用于处理 Promise、RxJS Stream。
它内部会 subscribe 和自动 unsubscribe Observable 非常方便。
当 Observable 处于未发布的时候,async pipe 会先返回 null 作为初始值。
Global Configuration
上面例子中有些 Pipe 使用时需要传入 parameters。比如 | currency : 'USD', | date : 'dd MMM yyyy'。
许多时候整个项目的 currency、date format 都是一致的。这时就需要一个 global config。
Pipe 的 global config 是利用 DI 来实现的。
如果想设置全局,可以到 app.config.ts 写入 provider 就可以了。
import { DATE_PIPE_DEFAULT_OPTIONS, DatePipeConfig } from '@angular/common';
import { ApplicationConfig, DEFAULT_CURRENCY_CODE } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [
{ provide: DEFAULT_CURRENCY_CODE, useValue: 'USD' },
{
provide: DATE_PIPE_DEFAULT_OPTIONS,
useValue: {
dateFormat: 'dd MMM yyyy',
timezone: '+0800', // if empty string, then Angular will use end-user's local system timezone
} satisfies DatePipeConfig,
},
],
};
DEFAULT_CURRENCY_CODE 和 DATE_PIPE_DEFAULT_OPTIONS 是 InjectionToken。
Use Pipe Transform in Any Where
大部分 Angular pipe 都提供了底层方法,所以可以用在任何地方
import { formatDate, formatCurrency, formatNumber, formatPercent} from '@angular/common';
console.log(formatDate(new Date(), 'dd MMM yyyy', 'en-US')); // 06 Apr 2023
console.log(formatCurrency(100, 'en-US', 'RM', 'MYR')); // RM100.00
当然,它们不在 DI 的 cover 范围,也就无法使用 global config 了。
如果想在组件内使用 pipe,可以通过 DI


DatePipe by default 是没有在 DI 中的,所以我们需要 provide。
可以在 app.config.ts provide,也可以通过 Component metadata provide(区别是什么,我会在接下来章节讲解,这里不展开)
然后注入就可以使用了。这样它就能使用到 global config 了。
Custom Pipe
上面提及的都是 Angular build-in 的 pipe。虽然挺多的,但在真实项目中依然会不够用。
幸好,Angular 允许我们自定义 Pipe。(Angular build-in 的 pipe 也是用同一种方式添加进项目的哦)
我们尝试做一个 AgoPipe
CLI command
ng g p ago
p for pipe
一开始长这样
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'ago',
standalone: true
})
export class AgoPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {
return null;
}
}
接着我们加入逻辑
import { InjectionToken, Pipe, PipeTransform, inject } from '@angular/core';
// 如果有需要 global config
export interface AgoPipeConfig {}
export const AGO_PIPE_CONFIG_TOKEN = new InjectionToken<AgoPipeConfig>(
'AgoPipeConfig'
);
// 底层方法
export function formatAgo(
date: Date,
param1?: string,
config: AgoPipeConfig | null = null
) {
console.log([date, param1, config]); // value, parameter, config
// do any transformation (这里我省略掉具体实现方法)
return '7 days ago';
}
@Pipe({
name: 'ago',
standalone: true,
})
export class AgoPipe implements PipeTransform {
private agoPipeConfig = inject(AGO_PIPE_CONFIG_TOKEN, { optional: true }); // 注入 global config
transform(date: Date, param1?: string): string {
// 调用底层方法
return formatAgo(date, param1, this.agoPipeConfig);
}
}
看注释理解,里面包含了 global config 和底层方法。类似 Angular 的 formatCurrency 和 DEFAULT_CURRENCY_CODE
在 app.config.ts 提供 global config
import { ApplicationConfig } from '@angular/core';
import { AgoPipeConfig, AGO_PIPE_CONFIG_TOKEN } from './ago.pipe';
export const appConfig: ApplicationConfig = {
providers: [
{ provide: AGO_PIPE_CONFIG_TOKEN, useValue: {} satisfies AgoPipeConfig },
],
};
在组件 imports AgoPipe
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, AgoPipe], // imports AgoPipe
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor() {}
today = new Date();
}
BTW, Angular build-in 的 pipe 是封装在 CommonModule 里的。
最后,在 template 使用
<h1>{{ today | ago }}</h1>
这样就可以了。
Pure
@Pipe({
name: 'ago',
standalone: true,
pure: false
})
pure 是 Pipe 的一个 config。默认是 true。它表示只有当 value 改变时才需要重新运行 transform 方法。
这个规则在某一些情况是不对的,比如 transform 依赖 config 的时候。因为不只是 value 改变会影响 transform 的结果,config 改变也可能影响 transform 的结果。
所以在这个情况下,我们需要把 pure 设置成 false。设置成 false 以后,不仅仅是当 value 改变,只要当前的组件 re-render(DoCheck 执行不代表 re-render 哦,要 dirty 才会 re-render),transform 就会执行。
至于这个 re-render 是什么概念,我会在后面 Change Detection 章节详细讲解。
Override Built-in Pipe
built-in pipe 很好,但也不是万能的,遇到不合适的场景还是需要魔改一下。这里提供一些魔改方案。
让 CurrencyPipe 支持 Big.js
CurrencyPipe 只支持 number | string | null | undefined

假如我的 value 类型是 Big.js 的 Big 对象,那就不能直接使用了。


最直接的解决方法就是调用 Big.toNumber 把 Big 对象转换成 number 类型。
<h1>{{ price.toNumber() | currency : 'MYR' : 'symbol-narrow' : '.2-2' }}</h1>
不过每次都要调用就很烦啊,我们能不能让 current pipe 支持 Big 对象,在调用 toNumber 封装起来?
可以,直接继承 CurrencyPipe 然后 override transform 方法
@Pipe({
name: 'currency',
standalone: true,
})
export class MyCurrencyPipe extends CurrencyPipe implements PipeTransform {
override transform(
value: number | Decimal | string,
currencyCode?: string,
display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean,
digitsInfo?: string,
locale?: string,
): string | null;
override transform(
value: null | Decimal | undefined,
currencyCode?: string,
display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean,
digitsInfo?: string,
locale?: string,
): null;
override transform(
value: number | Decimal | string | null | undefined,
currencyCode?: string,
display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean,
digitsInfo?: string,
locale?: string,
): string | null;
override transform(
value: number | Decimal | string | null | undefined,
currencyCode?: string,
display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean,
digitsInfo?: string,
locale?: string,
): string | null {
const convertedValue = value instanceof Decimal ? value.toNumber() : value;
return super.transform(convertedValue, currencyCode, display, digitsInfo, locale);
}
}
transform 方法本来就有很多 overload,所以我们得 override 每一个才行,真麻烦,
接着 imports 就可以了。

效果

没有报错了。
注:Pipe name 用回 'currency' 也不要紧,不会撞名字的。Angular compiler 会优先选择我们定义的 Pipe。
目录
上一篇 Angular 18+ 高级教程 – Component 组件 の Attribute Directives 属性型指令
下一篇 Angular 18+ 高级教程 – Change Detection & Ivy rendering engine
想查看目录,请移步 Angular 18+ 高级教程 – 目录
喜欢请点推荐,若发现教程内容以新版脱节请评论通知我。happy coding
Angular 18+ 高级教程 – Component 组件 の Pipe 管道的更多相关文章
- python学习笔记——multiprocessing 多进程组件 Pipe管道
进程间通信(IPC InterProcess Communication)是值在不同进程间传播或交换信息. IPC通过有管道(无名管道 和 有名 / 命名管道).消息队列.共享存储 / 内容.信号量. ...
- Angular CLI 使用教程指南参考
Angular CLI 使用教程指南参考 Angular CLI 现在虽然可以正常使用但仍然处于测试阶段. Angular CLI 依赖 Node 4 和 NPM 3 或更高版本. 安装 要安装Ang ...
- vue 基础-->进阶 教程(3):组件嵌套、组件之间的通信、路由机制
前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目. 本教程,将从零开始,教给大家vue的基础.高级操作.组件 ...
- 一篇文章看懂angularjs component组件
壹 ❀ 引 我在 angularjs 一篇文章看懂自定义指令directive 一文中详细介绍了directive基本用法与完整属性介绍.directive是个很神奇的存在,你可以不设置templa ...
- 分享25个新鲜出炉的 Photoshop 高级教程
网络上众多优秀的 Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享25个新鲜出炉的 Photoshop 高级教程,提高你的设计技巧,制作时尚的图片效果.这 ...
- Python第十一天 异常处理 glob模块和shlex模块 打开外部程序和subprocess模块 subprocess类 Pipe管道 operator模块 sorted函数 os模块 hashlib模块 platform模块 csv模块
Python第十一天 异常处理 glob模块和shlex模块 打开外部程序和subprocess模块 subprocess类 Pipe管道 operator模块 sorted函 ...
- [转帖]tar高级教程:增量备份、定时备份、网络备份
tar高级教程:增量备份.定时备份.网络备份 作者: lesca 分类: Tutorials, Ubuntu 发布时间: 2012-03-01 11:42 ė浏览 27,065 次 61条评论 一.概 ...
- Siki_Unity_2-9_C#高级教程(未完)
Unity 2-9 C#高级教程 任务1:字符串和正则表达式任务1-1&1-2:字符串类string System.String类(string为别名) 注:string创建的字符串是不可变的 ...
- angular里使用vue/vue组件怎么在angular里用
欢迎加入前端交流群交流知识&&获取视频资料:749539640 如何在angularjs(1)中使用vue参考: https://medium.com/@graphicbeacon/h ...
- angularjs中directive指令与component组件有什么区别?
壹 ❀ 引 我在前面花了两篇博客分别系统化介绍了angularjs中的directive指令与component组件,当然directive也能实现组件这点毋庸置疑.在了解完两者后,即便我们知道co ...
随机推荐
- 解决方案 | PPT右键复制文本时右键粘贴选项按钮为空白
1.问题 2.解决方法 随便复制一些文字,不要采用CRTL+V,而是采用右键粘贴方法到ppt中,选择纯文本的"A"符号. 之后再使用CTRL+C复制,CTRL+V即正常.(好像只能 ...
- Windows 10 LTSC中个人版OneDrive失效的问题
该问题是由于LTSC注册表无onedriver的id{A52BBA46-E9E1-435f-B3D9-28DAA648C0F6}定义导致,解决方案是新建一个reg_onedrive.reg文件,并编辑 ...
- mysql:Windows修改MySQL数据库密码(修改或忘记密码)
今天练习远程访问数据库时,为了方便访问,就想着把数据库密码改为统一的,以后我们也会经常遇到MySQL需要修改密码的情况,比如密码太简单.忘记密码等等.在这里我就借鉴其他人的方法总结几种修改MySQL密 ...
- 强烈推荐:18.3k star,推荐一款简单易用的HTTP请求流量录制回放工具:Goreplay
在软件开发和测试过程中,我们经常需要对应用程序的网络请求进行录制和回放,以便进行性能分析.压力测试或者模拟复杂的网络环境.今天,我要向大家推荐一款简单易用的 HTTP 请求流量录制回放工具:Gorep ...
- electron安装成功记录
1.登录官网查看当前最新版本对应的node,注意这里不要看php那个汉化的,他那个是老版本的,node对不上 2.nvm安装一个新的node 3.使用cnpm安装(npm安装还是报错了,记得删node ...
- Linux安装软件命令详解
Linux安装软件命令详解 目录 一.deb包的简介.安装及卸载步骤 二.rpm包的简介.安装及卸载步骤 三.AppImage包的简介.执行步骤 四.tar.gz.tar.bz2源代码包的简介.安装及 ...
- 【JS】05 DOM 文档对象模型 P2 元素的CRUD、Dom集合对象
Element & Node 元素,或者称为节点 在JS中创建一个HTML元素,但是因为没有指定在Dom对象中的节点位置,所以页面不会发生改变 var para = document.crea ...
- Linux系统下使用pytorch多进程读取图片数据时的注意事项——DataLoader的多进程使用注意事项
原文: PEP 703 – Making the Global Interpreter Lock Optional in CPython 相关内容: The GIL Affects Python Li ...
- MD5签名生成,字典排序,实际生产
1.背景 作用:防止请求参数篡改,限制请求时效性: 常用方式:md5签名 关键:签名Key 常用签名原串排列:字母顺序.key1=value1&key2=value2....key (注意:签 ...
- 海豚调度任务类型Apache SeaTunnel部署指南
Apache DolphinScheduler已支持Apache SeaTunnel任务类型,本文介绍了SeaTunnel任务类型如何创建,任务参数,以及任务样例. 一.Apache SeaTunne ...