angularjs自定义过滤器使用方法

了解为什么 Angular 不附带过滤和排序管道以及如何创建自定义过滤管道

七爪源码:为什么以及如何在 Angular 中创建不纯的过滤器管道

Angular 为最常见的场景提供了几个内置管道。

最大的缺席之一是过滤管。 Angular 不提供内置过滤器管道是有充分理由的。

为什么 Angular 不附带过滤管

Angular 中没有用于过滤和排序列表的管道,尽管 AngularJS 曾经提供 filter 和 orderBy。

这不是一个错误。

因为这样的管道性能很差并且禁止激进的缩小,Angular 并没有开箱即用地提供它们。 过滤成本很高。

尽管计算能力每年都在增长,但数据和信息也在不断增长!

七爪源码:为什么以及如何在 Angular 中创建不纯的过滤器管道

一般来说,过滤需要与对象属性对应的参数。 然而,有些场景要求管道是不纯的,这意味着 Angular 几乎在每次更改检测周期发生时都会调用不纯管道。

因此,过滤和排序成为代价高昂的操作,尤其是在数据量很大的情况下。

当 Angular 每秒多次调用这些管道时,即使是中等大小的列表,用户体验也可能会受到很大影响。

如何创建纯 FilterPipe

首先,让我们看一下模板和类。

应用组件和数据

在模板中,我们有一个输入元素,它使用双向绑定将用户输入存储在一个名为 filterBy 的属性中。 请记住在 AppModule 中导入 FormsModule 以在您的应用程序中使用双向绑定。

下面,我们使用 NgFor 从 usersList 中列出一些用户的名字。 这是代码:

<div> <label for="filter">Filter by: </label> <input type="text" id="filter" [(ngModel)]="filterBy" /></div><div *ngFor="let user of usersList> <ul> <li>{{ user.name }}</li> </ul></div>

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 中找到它。

每个用户都是一个具有多个属性的对象。 对于我们的目的,知道其中一个属性是名称就足够了。

我们想按名称过滤用户。

初始应用程序如下所示:

七爪源码:为什么以及如何在 Angular 中创建不纯的过滤器管道

创建 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? 是我们将用于过滤值的可选参数。

要使用此过滤器,我们只需将其添加到模板中,如下所示:

<div *ngFor="let user of usersList | filter">

自然,什么都不会发生。但是,请注意 usersList 是通过管道的属性,并且与 transform 方法中的 value 参数相关联。

将过滤代码添加到 FilterPipe

我们现在将在 FilterPipe 中的 transform 方法中工作。

变换方法的参数

首先,我们使用以下代码更新 transform 方法的参数:

transform(value: User[], filterString: string, property: string)

我们在上面讨论了价值。值的类型是形状像用户界面的对象数组。您可以在 StackBlitz 的 model.ts 中看到这一点。

第二个参数是 string 类型的 filterString。 filterString 的值必须来自模板。因此,我们将向管道添加一个参数。参数将是 filterBy ,即用户输入,例如,用户想要用作过滤器的字符串。

第三个也是最后一个论点是财产。由于我们的用户对象包含多个属性,因此我们需要指定要使用的属性。为了简单起见,我将字符串名称硬编码为模板中过滤器管道的第二个参数。

这是一个例子。通常,您不应该在代码中硬编码值。

在模板中,管道变为:

...<div *ngFor="let user of usersList | filter: filterBy:'name'"> <ul> <li>{{ user.name }}</li> </ul></div>

其中 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:

<button (click)="onAddUser()">Add user</button>

该方法如下所示:

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 异步管道优化了更改检测,但它也消除了手动使用订阅和取消订阅的必要性。

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:dandanxi6@qq.com

(0)
上一篇 2023年 2月 3日 下午12:22
下一篇 2023年 2月 3日 下午12:29

相关推荐

  • 不用数据线,不联网,手机也能和电脑共享文件吗

    #大有学问#当你们看到这个题目,肯定会疑问:没有数据线连接,不连接网络怎么可能让手机和电脑共享文件呢?其实,确实是真的方法。一起看看吧。 没有网络支持,也不用数据线,手机和电脑之间…

    2023年 8月 25日
  • 广东招募5000名乡村振兴志愿者

    日前,广东高校毕业生志愿服务乡村振兴行动(下称“志愿服务乡村振兴行动”)正式启动报名,招募对象主要为普通高等学校应届毕业生或在读研究生。2023年项目计划新招募选派志愿者约5000…

    2023年 7月 29日
  • 为什么我说话没有水平呢

    美国词典编撰者韦伯斯特曾经说过,如果你把他所有的财产都拿走,只留下他的词语,那么他可以把所有财产再挣回来。可见,语言的力量非常强大。 好文章和普通文章,好的话语和普通话语,一个很大…

    2023年 10月 22日
  • aso关键词优化工具,如何通过aso优化筛选关键词

    开发者历经了千辛万苦开发出了一款APP后,下一步就是将APP提交到各大应用平台以供用户下载。常见的应用平台有APPStore与安卓市场的各大应用商店,介于安卓应用商店众多,个人建议…

    2023年 6月 12日
  • 找图不求人!10个以图搜图的识图网站推荐

    常常有网友在网上评论“跪求图片出处”,为了某张图片要各处搜索,且往往都会搜到带水印、模糊不清的图片,甚是烦人。今天,小编就给大家推荐4个精选的搜图网站,让你轻松找到你所想要的图片!…

    2023年 2月 27日
  • 平面设计:ai中的字体设计变形,附带教程是什么

    效果图 做设计的朋友都知道,字体设计是最难的,前段时间,一个公司还是因字体侵权问题引发了大家关注,那就是微软雅黑,这款字体不是免费商用的,虽然下载PS,Ai都是自带的,但确不是免费…

    2023年 5月 3日
  • 怎么用手机提取图片的文字内容

    作为学生党,最头疼的应该就是笔记的整理问题,有时候上课拍了很多的笔记,但没有及时整理,等到需要整理的时候就会发现积累了很多。 但如果学会如何将图片中的文字提取出来就会简单很多了。 …

    2023年 3月 19日
  • 美团平台的数字人民币专区

    欧阳剑环 中国证券报·中证网 中证网讯(记者 欧阳剑环)1月21日,美团宣布开启电影演出场景的数字人民币支付通道。北京、上海、深圳等试点地区居民可用数字人民币在美团平台预订电影演出…

    互联网 2023年 5月 3日
  • 为什么要给影视剧主角开微博(为什么电视剧里没有的人要发微博)

    《冰雨火》中的陈宇微博以名字和警号“小宇852058”命名,《亲爱的,热爱的》中的韩商言微博认证信息是“KK俱乐部老板”,《余生,请多指教》中@顾魏gw 微博分享着医学小知识,《你…

    2022年 12月 29日
  • 家里小孩会不会误操作智能家居(长宁区常见智能家居处理方法)

    智能家居的应用,其实远远不像看上去的那么简单,对于现在的设备只要我们愿意打开脑洞,就能搞定更多有意思的新功能。 比如,今天要说的,就是如何让你的智能家居系统帮助你带娃。 设备介绍 …

    2023年 2月 4日