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年 3月 24日
  • wifi信号弱教你一招快速解决

    大家好,这里是@实用数码笔记,分享各种实用的数码小技巧,期待您的点赞和关注。 本文字数3600+字,写了六个小时多,[送心]详细地介绍了各种提升WiFi信号,优化网络速度的办法,希…

    2023年 9月 18日
  • 百元大钞飞出金凤凰(怎样能看到一百元里面的金凤凰)

    网传一百元可以扫出金凤凰。是真的吗?确实是真的,因为我扫过,今天闲来无事又扫了一下,原来不止一百元哦! 或许你也扫过,不过可以在回味一下。 若你用一百元没有扫出来金凤凰,那一定是操…

    2023年 1月 22日
  • 360可以把软件卸载干净吗,360残余文件夹怎么卸载干净

    如果你想彻底卸载360软件,不留任何残留文件和注册表,那么你需要使用一款专业的卸载工具,比如Geek Uninstaller。这款软件可以帮你快速、干净地删除360软件,不需要你手…

    2023年 9月 18日
  • 罗列一下学习Java编程的4个步骤

    经常会有想学习Java的朋友问道:石家庄Java培训哪家好?目前市面上Java培训机构众多,对于想要学习Java的人来说难免会不知道该如何选择。下面,千锋石家庄Java培训小编就给…

    2023年 6月 24日
  • 微信群聊汇总怎么弄(微信群转换成社群成功率)

    微信群总览包括社群列表和图表总览。 通过点击“查询”按钮可以获取已经接入系统的所有微信群信息。你也可以通过“群类别”和“微信群”下列框选取你所需要的微信群,日期起始区间指在这一个日…

    2023年 3月 13日
  • qq迎来内测更新加入了5个新功能

    11 月初,腾讯 QQ 正内测「QQ 频道」的消息逐渐传开了。 「QQ 频道」是一个全新的功能,QQ 称其为「娱乐协作新方式」,你可以通过它找到志同道合的伙伴,即便你们来自不同地方…

    2023年 2月 3日
  • 电脑笔记本怎么连接手机热点上网

    虽然手机是我们平时最常用的电子设备,但有些工作还是使用电脑效率更高,比如,编辑文档,查询下载资料,发送一些特殊文件等等。 但一些特定的环境下,你的电脑不能上网怎么办呢?这时是可以利…

    2023年 6月 9日
  • 头盔保质期过了需不需要换

    最近,江苏常州, 一起交通事故让人揪心, 两辆摩托车迎面相撞, 一死一伤, 遇难骑手年仅23岁, 让人感叹生命脆弱的同时, 据公安交管部门统计, 摩托车、电动自行车 是导致交通死亡…

    2023年 5月 8日
  • 花呗借呗钱不还有什么后果

    “遇事不决找花呗”,相信现在的人都多多少少有接触过阿里的产品,而如果当自己账户金额不够时,大多数人可能都会选择用花呗来消费。花呗作为阿里旗下蚂蚁金服所推出的产品,受到了多数用户的青…

    2023年 7月 23日