首页 > web前端 > js教程 > 正文

Angular数据列表多字段过滤功能的开发实践

碧海醫心
发布: 2025-11-20 20:46:01
原创
687人浏览过

Angular数据列表多字段过滤功能的开发实践

本教程详细介绍了如何在angular项目中实现数据列表的多字段模糊搜索功能。通过优化现有的单字段过滤逻辑,我们将展示如何利用`array.prototype.filter`结合逻辑或操作符,同时对用户列表的姓名、姓氏、用户名和邮箱等多个字段进行高效、大小写不敏感的过滤,从而显著提升用户体验和数据检索的灵活性。

在Angular应用开发中,数据列表的过滤功能是常见的需求。通常,用户希望能够通过输入一个关键词,在多个数据字段中进行模糊匹配,以快速定位所需信息。本文将指导您如何将一个仅支持单字段(如姓氏)过滤的功能扩展为支持多字段(如姓名、姓氏、用户名、邮箱)的灵活搜索。

1. 了解现有过滤机制

在原始实现中,过滤功能仅针对用户的lastName字段:

HTML 模板 (片段):

<input type="text" [(ngModel)]="lastname" (input)="Search()"/>
<!-- ... mat-table ... -->
登录后复制

TypeScript 组件逻辑 (片段):

export class GerenciamentoUsuariosListaComponent implements OnInit {
  @Input() usuarios: any[] = []; // 当前显示的用户列表
  _allUsuarios: any[] = []; // 用于存储原始、完整的用户列表
  lastname: string = ''; // 旧的搜索字段名,我们将用更通用的 searchTerm 替换

  // ... constructor, ngOnInit, refreshListUser1 ...

  Search(){
    if(this.lastname != ""){
      this.usuarios = this.usuarios.filter(res =>{
        return res.lastName.toLocaleLowerCase().match(this.lastname.toLocaleLowerCase());
      })
    }else if(this.lastname == ""){
      // 原始实现中这里会调用 ngOnInit() 重新获取数据,这并非最佳实践。
      // 更好的方式是从 _allUsuarios 恢复数据。
      this.ngOnInit();
    }
  }
}
登录后复制

上述代码存在两个主要问题:

  1. 只过滤了lastName一个字段。
  2. 当搜索框为空时,调用ngOnInit()会重新发起网络请求,这在大多数情况下是不必要的,且效率低下。

2. 优化组件数据管理

为了实现多字段过滤并避免不必要的网络请求,我们需要在组件中维护两份用户列表:一份是完整的原始数据,另一份是用于显示和过滤的数据。

  1. 引入 _allUsuarios 存储原始数据: 在组件类中声明一个私有变量 _allUsuarios 来保存从服务获取到的全部用户数据。

  2. 修改 refreshListUser1() 方法: 当数据从服务加载完成后,将数据同时赋值给 _allUsuarios 和 usuarios。usuarios 将是我们在模板中绑定的显示列表。

  3. 使用通用搜索词 searchTerm: 将 lastname 变量重命名为更具通用性的 searchTerm,以反映它现在可以匹配多个字段。

更新后的组件变量和数据加载:

import { Component, OnInit, Input } from '@angular/core';
import { GerenciamentoUsuariosService } from './gerenciamento-usuarios.service'; // 假设服务路径

export class GerenciamentoUsuariosListaComponent implements OnInit {
  @Input() usuarios: any[] = []; // 用于在模板中显示和过滤的用户列表
  _allUsuarios: any[] = []; // 存储从服务获取的完整用户列表
  searchTerm: string = ''; // 通用搜索关键词

  readonly displayedColumns = ['firstName', 'lastName', 'username', 'email', 'actions'];

  constructor(private service: GerenciamentoUsuariosService) {}

  ngOnInit(): void {
    this.refreshListUser1();
  }

  refreshListUser1() {
    this.service.list().subscribe(
      resp => {
        this._allUsuarios = resp.content; // 将完整数据存储到 _allUsuarios
        this.usuarios = [...this._allUsuarios]; // 初始化显示列表为完整列表
        console.log(this.usuarios);
      }
    );
  }

  // ... Search() 方法将在下一步中更新
}
登录后复制

3. 实现多字段过滤逻辑

核心的改变在于 Search() 方法。我们将使用 Array.prototype.filter() 结合逻辑或 (||) 操作符来检查多个字段是否包含搜索关键词。

1.1.8PbootCMS
1.1.8PbootCMS

PbootCMS是一款高效、简洁、强悍的开源PHP企业网站开发建设管理系统。 PbootCMS 1.1.8 更新日志:2018-08-07 1.修复提交表单多选字段接收数据问题; 2.修复登录过程中二次登陆在页面不刷新时验证失败问题; 3.新增搜索结果fuzzy参数来控制是否模糊匹配; 4.新增父分类,顶级分类名称及链接独立标签,具体见手册; 5.新增内容多图拖动排序功能。

1.1.8PbootCMS 243
查看详情 1.1.8PbootCMS

更新后的 Search() 方法:

// ... (组件的其他部分保持不变)

  Search() {
    // 检查搜索关键词是否为空或只包含空白字符
    if (this.searchTerm.trim() !== "") {
      const keyword = this.searchTerm.toLocaleLowerCase().trim(); // 转换为小写并去除首尾空格

      this.usuarios = this._allUsuarios.filter(res => {
        // 对每个字段进行大小写不敏感的模糊匹配,使用 || 连接多个条件
        return res.firstName.toLocaleLowerCase().includes(keyword) ||
               res.lastName.toLocaleLowerCase().includes(keyword) ||
               res.username.toLocaleLowerCase().includes(keyword) ||
               res.email.toLocaleLowerCase().includes(keyword);
      });
    } else {
      // 如果搜索关键词为空,则将显示列表重置为完整的原始列表
      this.usuarios = [...this._allUsuarios];
    }
  }
}
登录后复制

4. 更新 HTML 模板

最后,将 HTML 模板中的 [(ngModel)] 绑定从 lastname 更新为新的 searchTerm。

更新后的 HTML 模板 (片段):

<input type="text" [(ngModel)]="searchTerm" (input)="Search()"/>

<mat-table [dataSource]="usuarios">
    <!-- Name Column -->
    <ng-container matColumnDef="firstName">
      <mat-header-cell *matHeaderCellDef> Nome </mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.firstName }}</mat-cell>
    </ng-container>
    <!-- Last Name Column -->
    <ng-container matColumnDef="lastName">
      <mat-header-cell *matHeaderCellDef>Sobrenome</mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.lastName }}</mat-cell>
    </ng-container>
    <!-- UserName Column -->
    <ng-container matColumnDef="username">
        <mat-header-cell *matHeaderCellDef>Username</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.username }}</mat-cell>
      </ng-container>
      <!-- Email Column -->
      <ng-container matColumnDef="email">
        <mat-header-cell *matHeaderCellDef>E-mail</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.email }}</mat-cell>
      </ng-container>
      <!-- ... 其他列和操作 ... -->
</mat-table>
登录后复制

5. 完整代码示例

gerenciamento-usuarios-lista.component.html

<input type="text" [(ngModel)]="searchTerm" (input)="Search()"/>

<mat-table [dataSource]="usuarios">
    <!-- Name Column -->
    <ng-container matColumnDef="firstName">
      <mat-header-cell *matHeaderCellDef> Nome </mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.firstName }}</mat-cell>
    </ng-container>
    <!-- Last Name Column -->
    <ng-container matColumnDef="lastName">
      <mat-header-cell *matHeaderCellDef>Sobrenome</mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.lastName }}</mat-cell>
    </ng-container>
    <!-- UserName Column -->
    <ng-container matColumnDef="username">
        <mat-header-cell *matHeaderCellDef>Username</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.username }}</mat-cell>
      </ng-container>
      <!-- Email Column -->
      <ng-container matColumnDef="email">
        <mat-header-cell *matHeaderCellDef>E-mail</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.email }}</mat-cell>
      </ng-container>
      <!-- 假设还有 'actions' 列 -->
      <ng-container matColumnDef="actions">
        <mat-header-cell *matHeaderCellDef> Ações </mat-header-cell>
        <mat-cell *matCellDef="let element">
          <!-- 您的操作按钮 -->
        </mat-cell>
      </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
登录后复制

gerenciamento-usuarios-lista.component.ts

import { Component, OnInit, Input } from '@angular/core';
// 假设您的服务路径和模型结构
import { GerenciamentoUsuariosService } from './gerenciamento-usuarios.service';

@Component({
  selector: 'app-gerenciamento-usuarios-lista',
  templateUrl: './gerenciamento-usuarios-lista.component.html',
  styleUrls: ['./gerenciamento-usuarios-lista.component.css']
})
export class GerenciamentoUsuariosListaComponent implements OnInit {
  @Input() usuarios: any[] = []; // 用于在模板中显示和过滤的用户列表
  _allUsuarios: any[] = []; // 存储从服务获取的完整用户列表
  searchTerm: string = ''; // 通用搜索关键词

  readonly displayedColumns = ['firstName', 'lastName', 'username', 'email', 'actions'];

  constructor(private service: GerenciamentoUsuariosService) {}

  ngOnInit(): void {
    this.refreshListUser1();
  }

  refreshListUser1() {
    this.service.list().subscribe(
      resp => {
        this._allUsuarios = resp.content; // 将完整数据存储到 _allUsuarios
        this.usuarios = [...this._allUsuarios]; // 初始化显示列表为完整列表
        console.log(this.usuarios);
      },
      error => {
        console.error('Error fetching user list:', error);
        // 处理错误情况,例如显示错误消息
      }
    );
  }

  Search() {
    // 检查搜索关键词是否为空或只包含空白字符
    if (this.searchTerm.trim() !== "") {
      const keyword = this.searchTerm.toLocaleLowerCase().trim(); // 转换为小写并去除首尾空格

      this.usuarios = this._allUsuarios.filter(res => {
        // 对每个字段进行大小写不敏感的模糊匹配,使用 || 连接多个条件
        return (res.firstName && res.firstName.toLocaleLowerCase().includes(keyword)) ||
               (res.lastName && res.lastName.toLocaleLowerCase().includes(keyword)) ||
               (res.username && res.username.toLocaleLowerCase().includes(keyword)) ||
               (res.email && res.email.toLocaleLowerCase().includes(keyword));
      });
    } else {
      // 如果搜索关键词为空,则将显示列表重置为完整的原始列表
      this.usuarios = [...this._allUsuarios];
    }
  }
}
登录后复制

注意事项:

  • 空值检查: 在进行 toLocaleLowerCase() 或 includes() 操作之前,最好检查字段是否存在(例如 res.firstName && res.firstName.toLocaleLowerCase().includes(keyword)),以防止某些用户对象缺少特定字段时抛出错误。
  • 性能优化: 对于非常庞大的数据集(数千条甚至更多),客户端进行全量过滤可能会影响性能。在这种情况下,考虑将过滤逻辑迁移到后端服务器,让服务器负责数据检索和过滤,只返回匹配的结果。
  • 防抖 (Debounce): (input) 事件会在每次按键时触发 Search() 方法。为了避免过于频繁的过滤操作(尤其是在用户快速输入时),可以考虑引入防抖机制,例如使用 rxjs 的 debounceTime 操作符,在用户停止输入一段时间后才执行搜索。
  • 用户体验: 可以在搜索框旁边添加一个清除按钮,方便用户快速清空搜索内容。

总结

通过以上步骤,我们成功地将一个基本的单字段过滤功能扩展为强大的多字段模糊搜索。核心思想是维护一份完整的原始数据列表,并在每次搜索时从这份原始数据中进行过滤,同时利用 Array.prototype.filter 和逻辑或操作符实现对多个字段的灵活匹配。这种方法不仅提高了代码的复用性和可维护性,也极大地增强了用户在数据列表中的检索能力。

以上就是Angular数据列表多字段过滤功能的开发实践的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号