如何在 Angular 中创建自定义管道,什么是纯管道和不纯管道,以及如何使用纯管道来提高应用程序的性能。Angular 中的管道是组件模板表达式中使用的函数,用于将值转换为其他显示格式。Angular 具有多个内置管道,如日期管道、异步管道等。但是,如果这些管道不能满足我们的需求,我们可以创建自己的管道。
在本文中,我们将研究:
如何在角度中创建自定义管道(手动/使用角度 CLI)
如何使用管道并传递额外的参数
什么是纯管道和不纯管道
如何通过纯管道和记忆提高性能
那么,让我们开始吧!
在角度中创建自定义管道
要创建自定义管道,我们需要遵循3个简单的步骤:
1. 创建一个类,并用装饰器装饰它。 装饰器必须包含我们将用于调用管道的 。@Pipename
2. 实现接口。这个接口有一个我们需要实现的方法:方法。PipeTransform transform
是应用管道的参数。称为“其余参数”。它被视为无限数量的可选参数(零个或多个)。如果我们不需要传递任何额外的参数,我们只传递第一个参数。最后,我们返回转换后的值。value...args
3. 在模块的数组中添加自定义管道 。declaration
从 Angular v14 开始,我们还可以在其模板中使用它,将管道添加到任何独立组件的数组中。imports
在 Angular 中创建和注册自定义管道的手动方法到此结束。
使用角度气候接口
如果这对你来说似乎需要做很多工作,请不要担心。我们已经为您准备好了!
角度 CLI 提供了一种生成拔模管道类的快速方法。它还会在 中注册管道。该命令为:AppModule
或简称:
例如,我们通过运行以下命令创建了管道:mark
CLI 生成了以下草稿管道类,准备将我们想要的任何逻辑放入方法中。transform
使用管道
使用管道的语法为:
例如,管道接收熊猫的性别并返回引导图标类。gender
奖金 — 我们也可能链条管道。执行顺序从左到右。
P评估额外参数
传递额外参数的语法为:
在我们的演示中,管道接收两个字符串值:要转换的值和搜索词。如果该值包含搜索词,则该搜索词带有下划线并变为红色。mark
我们还创建 CSS 类来定义样式。
最后,我们在模板中使用管道。
现在,如果我们搜索一只熊猫:
纯管
默认情况下,管道被定义为纯管道。 为了清楚起见,我们可以像这样显式设置纯属性:
该属性通知 Angular 该方法是纯的。puretruetransform
如果方法始终为相同的参数返回相同的结果,并且没有副作用(如修改参数、全局变量或除其返回值以外的任何其他内容),则该方法称为 pure。
Angular 知道,在这些条件下,除非输入值更改,否则方法的结果不会更改。因此,仅当检测到输入值发生更改时,它才会执行管道。transform
不纯管道
相反,通过将属性设置为,我们声明不纯管道。 Angular 每次检测到每次击键或鼠标移动的变化时,都会执行不纯的管道。purefalse
那么为什么有人想使用不纯的管道呢?
当我们想要检测复合对象中的不纯变化时,通常使用不纯管道。
将对象传递到管道时,Angular 仅检查参照的更改。如果对象属性内部发生任何更改,Angular 将无法分辨。
在任何情况下,使用不纯的管道都要格外小心。 官方文档指出,“长时间运行的不纯管道可能会大大减慢您的应用程序速度”。
提高应用程序性能
注意到当我们清除上一个GIF末尾的搜索输入字段时的巨大滞后吗?让我们看看导致此问题的原因,以及如何使用自定义管道解决此问题。
问题
问题的原因出在模板文件中,该文件调用该方法。PandaComponent calculatePopularity
在组件的类文件中,该方法使用当前熊猫的出生年份来计算其受欢迎程度。出于演示目的,我们使用斐波那契数列和未优化的递归实现。calculatePopularity
为什么在模板中调用方法会导致性能问题?
要回答这个问题,我们需要了解Angular的变化检测机制的基础知识。Angular 运行更改检测,以确定在发生更改时需要重新呈现 UI 的哪些部分。被调用方法的结果是 UI 的一部分。
Angular 如何知道方法的结果是否已更改?
不能!只有一种方法可以知道:再次执行它。换句话说,它将在每次检测到更改时运行该方法,即使更改无关紧要。
这将降低应用程序的性能。数量取决于被调用方法的作用。在我们的演示中,我们进行了繁重、重复、未优化的计算,因此我们之前观察到了延迟。
您还可以通过加载时间判断出问题。我们运行灯塔,它产生了以下分数。
注意:灯塔报告分数基于页面的加载时间,而不是与之交互时。
首次改进
作为第一步,我们将组件的策略更改为。这意味着,现在仅当其属性更改时,才会触发 内部的更改检测。changeDetection OnPushPandaComponent@Input
这大大缩短了装载时间。运行灯塔证实了这一改进。
这缩短了加载时间,但未缩短应用程序的交互时间。
这是因为每次我们键入内容时,我们都在执行搜索,这会更改对 的引用。filteredPandas
熊猫组件的输入属性也是如此。
因此,将再次调用其模板中的方法。calculatePopularity
纯管道救援
这就是纯管道发挥作用的地方。我们创建一个纯自定义管道,仅在管道的输入更改时才执行所需的计算。
然后,我们使用管道而不是调用该方法。现在,除非传递给管道的值发生更改,否则不会重新计算受欢迎程度。简单地说,我们不再计算结果中仍然可见的大熊猫的受欢迎程度。
这减少了交互时间,并使应用程序在大多数情况下顺利运行。因为加载时间没有变化,灯塔得分也没有变化。
纯管道和记忆
以前的改进是一些东西,但是为什么应用程序在最后仍然滞后?
当我们清除搜索字段时,所有大熊猫都变得可见。因此,以前隐藏的熊猫现在被重新渲染,它们的受欢迎程度必须重新计算。
我们能做得更好吗?是的,我们能!
如何?输入备注!
管道是纯的,因为斐波那契是纯函数。由于是这种情况,我们可以缓存计算,而不是从头开始重新计算它们。为此,我们通过运行以下命令来安装包:popularitymemo-decorator
npm install memo-decorator
然后,我们用装饰器装饰我们的方法。fibonacci@memo
这一行是否足以弥补差异?好吧,亲眼看看!
该应用程序加载速度要快得多,这也反映在灯塔分数中。
此外,交互变得尽可能顺利,没有任何滞后发生。
如果你得到的灯塔分数比我们低约 50 分,则可能是因为你在开发模式下运行应用程序。您需要将应用程序作为生产版本提供。为此,请执行以下操作:
安装服务器:npm install http-server -g
构建应用程序:ng build
服务于生产版本:http-server dist/ng-custom-pipe-demo
结论
在本文中,我们研究了 Angular 中的自定义管道。我们解释了如何创建、使用和传递额外的参数。我们看到了纯管道和不纯管道之间的差异。最后,我们将纯管道和记忆相结合,以提高应用程序的性能。