七爪源码为什么以及如何在Angular中创建不纯的过滤器管道
了解为什么 Angular 不附带过滤和排序管道以及如何创建自定义过滤管道
Angular 为最常见的场景提供了几个内置管道。
最大的缺席之一是过滤管。 Angular 不提供内置过滤器管道是有充分理由的。
为什么 Angular 不附带过滤管
Angular 中没有用于过滤和排序列表的管道,尽管 AngularJS 曾经提供 filter 和 orderBy。
这不是一个错误。
因为这样的管道性能很差并且禁止激进的缩小,Angular 并没有开箱即用地提供它们。 过滤成本很高。
尽管计算能力每年都在增长,但数据和信息也在不断增长!
一般来说,过滤需要与对象属性对应的参数。 然而,有些场景要求管道是不纯的,这意味着 Angular 几乎在每次更改检测周期发生时都会调用不纯管道。
因此,过滤和排序成为代价高昂的操作,尤其是在数据量很大的情况下。
当 Angular 每秒多次调用这些管道时,即使是中等大小的列表,用户体验也可能会受到很大影响。
如何创建纯 FilterPipe
首先,让我们看一下模板和类。
应用组件和数据
在模板中,我们有一个输入元素,它使用双向绑定将用户输入存储在一个名为 filterBy 的属性中。 请记住在 AppModule 中导入 FormsModule 以在您的应用程序中使用双向绑定。
下面,我们使用 NgFor 从 usersList 中列出一些用户的名字。 这是代码:
import { Component, VERSION } from "@angular/core"; import { User } from "./model"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"], }) export class AppComponent { name = "Angular " + VERSION.major; filterBy; usersList: User[] = [...] // omitted for clarity }
用户列表 usersList 是一个包含十个项目的数组,例如 users。 它存储在类中,您可以在 jsonplaceholder 或此应用的 StackBlitz 中找到它。
每个用户都是一个具有多个属性的对象。 对于我们的目的,知道其中一个属性是名称就足够了。
我们想按名称过滤用户。
初始应用程序如下所示:
创建 FilterPipe 类
让我们从使用 Angular CLI 命令 ng generate pipe filter 开始,其中 filter 是将在模板绑定中使用的管道名称。
作为旁注,您还可以使用 ng g p 管道。
Angular 将负责创建文件、填充一些字段并将其正确导入 app.module.ts。import { Pipe, PipeTransform } from "@angular/core"; @Pipe({ name: "filter" }) export class FilterPipe implements PipeTransform { transform(value: any, args?: any): any { return null; } }
在 transform 方法中,value 是模板中管道左侧的值,而 args? 是我们将用于过滤值的可选参数。
要使用此过滤器,我们只需将其添加到模板中,如下所示:
自然,什么都不会发生。但是,请注意 usersList 是通过管道的属性,并且与 transform 方法中的 value 参数相关联。
将过滤代码添加到 FilterPipe
我们现在将在 FilterPipe 中的 transform 方法中工作。
变换方法的参数
首先,我们使用以下代码更新 transform 方法的参数:transform(value: User[], filterString: string, property: string)
我们在上面讨论了价值。值的类型是形状像用户界面的对象数组。您可以在 StackBlitz 的 model.ts 中看到这一点。
第二个参数是 string 类型的 filterString。 filterString 的值必须来自模板。因此,我们将向管道添加一个参数。参数将是 filterBy ,即用户输入,例如,用户想要用作过滤器的字符串。
第三个也是最后一个论点是财产。由于我们的用户对象包含多个属性,因此我们需要指定要使用的属性。为了简单起见,我将字符串名称硬编码为模板中过滤器管道的第二个参数。
这是一个例子。通常,您不应该在代码中硬编码值。
在模板中,管道变为:...
其中 filter 是管道的名称,filterBy 是我们从输入元素中获得的属性,这要归功于双向绑定,而 "name" 是用户对象中的硬编码属性。
您需要的参数数量是可选的,根据您的需要。
transform方法中的过滤逻辑
现在我们在 transform 方法中工作。
我们首先添加一些代码以在没有过滤器时返回每个值。if (value.length === 0 || !filterString) { return value; }
然后,我们添加逻辑以根据用户的字符串进行过滤。 let filteredUsers: User[] = [];for (let user of value) { if (user[property].includes(filterString)) { filteredUsers.push(user); }}return filteredUsers;
请记住,属性是硬编码的,它意味着名称。 value 是 usersList 中的用户列表,filterString 是一个人想要用作过滤器的字符串,例如 filterBy。
因此,您可以将这段代码读作"对于userList中的每个用户,如果用户名包含filterBystring,则将此用户添加到filteredUsersarray"最终返回。
到目前为止,这是 FilterPipe:import { Pipe, PipeTransform } from "@angular/core"; import { User } from "./model"; @Pipe({ name: "filter", }) export class FilterPipe implements PipeTransform { transform(value: User[], filterString: string, property: string): User[] { if (value.length === 0 || !filterString) { return value; } let filteredUsers: User[] = []; for (let user of value) { if (user[property].toLowerCase().includes(filterString.toLowerCase())) { filteredUsers.push(user); } } return filteredUsers; } }
此时,管道允许我们很好地过滤名称。
请注意,我添加了 JavaScript toLowerCase() 方法,以便过滤器不区分大小写。 当然,这完全是可选的。
那么昂贵的过滤操作呢?
如何使 FilterPipe 不纯
让我们更进一步。
我们添加一个简单的按钮,使用以下代码将新用户添加到 usersList:
该方法如下所示: onAddUser() { this.usersList.push({ id: Math.floor(Math.random() * 10000), name: "Leanne Graham", username: "Bret", ... }); }
每次单击时,都会将一个用户推送到 usersList。
这就是问题所在!
如果您过滤 Leanne,然后单击该按钮,则用户将添加到 usersList,但不会呈现过滤后的列表。因此,您不会在过滤列表中看到新用户,即使您在删除过滤器后会立即看到它们。
每次复合数组或对象更改时,Angular 都不会在数据上重新运行管道。
纯净和不纯净的管道
更准确地说,我们需要谈谈纯管道和非纯管道。
当输入值发生纯变化时,我们有一个纯管道。纯粹的更改可以是以下之一:对原始输入值(字符串、数字、布尔值、符号)的更改对对象引用(日期、数组、函数、对象)的更改
纯管道使用纯函数。给定相同的输入,纯函数应该总是返回相同的输出。
默认情况下,管道是纯的,因为 Angular 忽略了对象或数组内部的变化。因此,当我们添加到输入数组时,它不会调用纯管道,就像我们的例子一样,或者更新输入对象属性。
您可以猜到,对象引用检查比深度检查差异更快。此外,当 Angular 跳过管道执行时,它也会跳过视图更新。
因此,当常规变化检测策略很好时,最好使用纯管道。
当我们需要进行深度检查时,例如在当前示例中,我们需要使用不纯管道。
在每个组件变化检测周期中都会有一条不纯的管道运行。例如,它可以在每次击键或鼠标移动时运行。
你可以猜到,这很快就变得非常昂贵。
话虽如此,实现不纯管道就像在管道装饰器中声明 pure: false 一样简单。@Pipe({ name: "filter", pure: false, })
通过将 pure 属性添加到 Pipe 装饰器,我们强制 FilterPipe 在每次数据更改时更新。
在管道内添加一个日志以可视化频率。
使用不纯管道可能会导致性能和激进的最小化问题。 因此,请谨慎使用,仅在真正需要时使用。
在 StackBlitz 上查找代码或从 GitHub 克隆应用程序。
异步管道
作为旁注,值得一提的是异步管道是不纯的。 粗略地说,我们可以争辩说"管道总是在检查新的输入数据时是不纯的"。
虽然 Angular 异步管道优化了更改检测,但它也消除了手动使用订阅和取消订阅的必要性。
黑砂迷魂制敌手,声东击西,比拳更具摧毁力的掌法搏击格斗阴招头条创作挑战赛功夫武术酷整理了一套黑砂迷魂制敌手的实战用法,分享给大家。本篇是阴阳八卦断命手,拐头击面撩裆砍颈,直击要害,简单凶狠的续篇。一戳面击胸我方左脚前上成弓步,同时左掌向敌
距离下一个张玉宁,温州还有多远潮新闻记者戚祥浩瓯江观察是浙报集团温州分社创办的重点栏目,围绕中心,聚焦热点,从全省乃至全国看温州,让读者在浙里读懂温州。4月14日下午,温州足坛再传振奋人心消息,温籍球员张玉宁力
开展全面调查!中国篮协CBA联赛深夜通报4月14日,上海男篮108比104江苏男篮,挺进季后赛次轮,江苏男篮决胜时刻连续三次失误葬送好局。赛后,假球江苏男篮连续失误上海男篮战胜江苏男篮登上热搜引发争议。4月15日凌晨1时
首日!四金!据黑龙江交通广播消息14日2023年跳水世界杯西安站拉开帷幕中国跳水梦之队仿佛开启金牌收割机模式包揽了比赛首日全部4枚金牌网友纷纷点赞特别优秀!特别棒!女子双人十米台全红婵陈芋汐夺
谢天谢地谢亚龙,李铁李楠李春江众所周知,谢亚龙李铁是中国足球界的老鼠屎,而李楠和李春江在篮球界也属于此等货色。李楠作为一名党员一名军人,做出如此龌龊之事,令球迷费解。在CBA季后赛的生死之战中,李楠作为主教练看
沈阳京剧院沉浸式体验活动让国粹活起来来源沈阳日报沈阳网当国粹遇见书房,会碰撞出怎样的火花?4月14日,由中共沈阳市委宣传部沈阳市文化旅游和广播电视局主办的沈阳市艺术惠民双百万工程公益惠民演出国韵书香活态传承国粹艺术沉
怒波走世界巴拿马的龙虾怒波走世界南美,你如此悲怆巴拿马老炮台黄土地上望星空窑洞文化撞击企业家精神2013年5月17日的13点30分,我第三次登顶珠峰。下撤时,坐在8750米的第三台阶上俯视这个世界。乱云
有排面!徕卡CEO亲自拜访雷军,为小米13Ultra打出满分今年国产旗舰手机扎堆亮相,发布会场面一家比一家宏大,真让广大网友大饱眼福,但是真要说有排面还得说小米13Ultra手机。日前,徕卡CEOMatthiasHarsch亲自来中国,前往
iPhone15mini曝光定价3499元起,挑战苹果最佳性价比手机喜欢苹果手机的朋友,相信很大一部分选择iphone的主要原因就包括iphone小屏旗舰的优秀质感。当年iPhone12mini的推出,是小屏手机党的福音,但到了iphone14就被
中国芯片产业在美国的重重包围下,取得重大突破华为轮值董事长徐直军5日表示,受美国制裁影响,中国芯片产业将取得重大突破。在过去几年里,美国一直试图通过制裁和出口限制切断中国和中国企业的联系,华为沿着其他国内公司共同开发了制造1
工业互联网建设要关注三个导向工业互联网应该怎么去推进?置顶的关键是要始终不忘初心。这个初心,指的是要解决问题,以达到提质增效降本绿色安全的目的,并为此有的放矢地去做网络平台数据和安全方面的建设。遗憾的是,在实