介绍

Pipe 类似于 Template Syntax,它的用途是 transform value for display。

参考:

Docs – Understanding Pipes

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,有好几个选择:

  1. 'code' 表示显示 currency code

  2. 'symbol' 表示显示符号就够了。Angular 会把 code 转成对应的 symbol,比如 USD -> $

  3. 'symbol-narrow' 也是显示 symbol 但是是 "narrow" 版,马来西亚的 symbol-narrow 是 'RM' Ringgit Malaysia 的缩写

  4. '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 常用于处理 PromiseRxJS 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 管道的更多相关文章

  1. python学习笔记——multiprocessing 多进程组件 Pipe管道

    进程间通信(IPC InterProcess Communication)是值在不同进程间传播或交换信息. IPC通过有管道(无名管道 和 有名 / 命名管道).消息队列.共享存储 / 内容.信号量. ...

  2. Angular CLI 使用教程指南参考

    Angular CLI 使用教程指南参考 Angular CLI 现在虽然可以正常使用但仍然处于测试阶段. Angular CLI 依赖 Node 4 和 NPM 3 或更高版本. 安装 要安装Ang ...

  3. vue 基础-->进阶 教程(3):组件嵌套、组件之间的通信、路由机制

    前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目. 本教程,将从零开始,教给大家vue的基础.高级操作.组件 ...

  4. 一篇文章看懂angularjs component组件

     壹 ❀ 引 我在 angularjs 一篇文章看懂自定义指令directive 一文中详细介绍了directive基本用法与完整属性介绍.directive是个很神奇的存在,你可以不设置templa ...

  5. 分享25个新鲜出炉的 Photoshop 高级教程

    网络上众多优秀的 Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享25个新鲜出炉的 Photoshop 高级教程,提高你的设计技巧,制作时尚的图片效果.这 ...

  6. Python第十一天 异常处理 glob模块和shlex模块 打开外部程序和subprocess模块 subprocess类 Pipe管道 operator模块 sorted函数 os模块 hashlib模块 platform模块 csv模块

    Python第十一天    异常处理  glob模块和shlex模块    打开外部程序和subprocess模块  subprocess类  Pipe管道  operator模块   sorted函 ...

  7. [转帖]tar高级教程:增量备份、定时备份、网络备份

    tar高级教程:增量备份.定时备份.网络备份 作者: lesca 分类: Tutorials, Ubuntu 发布时间: 2012-03-01 11:42 ė浏览 27,065 次 61条评论 一.概 ...

  8. Siki_Unity_2-9_C#高级教程(未完)

    Unity 2-9 C#高级教程 任务1:字符串和正则表达式任务1-1&1-2:字符串类string System.String类(string为别名) 注:string创建的字符串是不可变的 ...

  9. angular里使用vue/vue组件怎么在angular里用

    欢迎加入前端交流群交流知识&&获取视频资料:749539640 如何在angularjs(1)中使用vue参考: https://medium.com/@graphicbeacon/h ...

  10. angularjs中directive指令与component组件有什么区别?

     壹 ❀ 引 我在前面花了两篇博客分别系统化介绍了angularjs中的directive指令与component组件,当然directive也能实现组件这点毋庸置疑.在了解完两者后,即便我们知道co ...

随机推荐

  1. 解决方案 | PPT右键复制文本时右键粘贴选项按钮为空白

    1.问题 2.解决方法 随便复制一些文字,不要采用CRTL+V,而是采用右键粘贴方法到ppt中,选择纯文本的"A"符号. 之后再使用CTRL+C复制,CTRL+V即正常.(好像只能 ...

  2. Windows 10 LTSC中个人版OneDrive失效的问题

    该问题是由于LTSC注册表无onedriver的id{A52BBA46-E9E1-435f-B3D9-28DAA648C0F6}定义导致,解决方案是新建一个reg_onedrive.reg文件,并编辑 ...

  3. mysql:Windows修改MySQL数据库密码(修改或忘记密码)

    今天练习远程访问数据库时,为了方便访问,就想着把数据库密码改为统一的,以后我们也会经常遇到MySQL需要修改密码的情况,比如密码太简单.忘记密码等等.在这里我就借鉴其他人的方法总结几种修改MySQL密 ...

  4. 强烈推荐:18.3k star,推荐一款简单易用的HTTP请求流量录制回放工具:Goreplay

    在软件开发和测试过程中,我们经常需要对应用程序的网络请求进行录制和回放,以便进行性能分析.压力测试或者模拟复杂的网络环境.今天,我要向大家推荐一款简单易用的 HTTP 请求流量录制回放工具:Gorep ...

  5. electron安装成功记录

    1.登录官网查看当前最新版本对应的node,注意这里不要看php那个汉化的,他那个是老版本的,node对不上 2.nvm安装一个新的node 3.使用cnpm安装(npm安装还是报错了,记得删node ...

  6. Linux安装软件命令详解

    Linux安装软件命令详解 目录 一.deb包的简介.安装及卸载步骤 二.rpm包的简介.安装及卸载步骤 三.AppImage包的简介.执行步骤 四.tar.gz.tar.bz2源代码包的简介.安装及 ...

  7. 【JS】05 DOM 文档对象模型 P2 元素的CRUD、Dom集合对象

    Element & Node 元素,或者称为节点 在JS中创建一个HTML元素,但是因为没有指定在Dom对象中的节点位置,所以页面不会发生改变 var para = document.crea ...

  8. Linux系统下使用pytorch多进程读取图片数据时的注意事项——DataLoader的多进程使用注意事项

    原文: PEP 703 – Making the Global Interpreter Lock Optional in CPython 相关内容: The GIL Affects Python Li ...

  9. MD5签名生成,字典排序,实际生产

    1.背景 作用:防止请求参数篡改,限制请求时效性: 常用方式:md5签名 关键:签名Key 常用签名原串排列:字母顺序.key1=value1&key2=value2....key (注意:签 ...

  10. 海豚调度任务类型Apache SeaTunnel部署指南

    Apache DolphinScheduler已支持Apache SeaTunnel任务类型,本文介绍了SeaTunnel任务类型如何创建,任务参数,以及任务样例. 一.Apache SeaTunne ...