讲师中心 微信公众号
AI工具推荐 视频效率加速

在Angular项目中实现高效多字段模糊搜索与数据过滤

夜辰吖_9926

夜辰吖_9926

发布时间:2025-11-20 20:06:16

|

574人浏览过

|

来源于php中文网

原创

在Angular项目中实现高效多字段模糊搜索与数据过滤

本教程详细指导如何在angular应用中为数据列表实现多字段模糊搜索功能。我们将从现有单字段过滤逻辑出发,逐步优化为支持姓名、邮箱、用户名等多个字段的灵活查询。教程将深入探讨如何利用javascript的数组和字符串方法进行高效过滤,并介绍如何有效管理原始数据与过滤结果,确保搜索体验流畅且高效。

1. 理解数据过滤与模糊匹配的核心概念

在Web应用中,数据列表的过滤是一个常见需求。用户通常希望通过输入关键词来快速查找相关信息。实现这一功能的核心在于以下几个JavaScript数组和字符串方法:

  • Array.prototype.filter(): 这是JavaScript数组的一个高阶函数,它创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。它是实现数据过滤的基础。
  • String.prototype.toLocaleLowerCase(): 此方法将字符串转换为小写,通常用于实现大小写不敏感的比较,确保搜索结果的全面性。
  • String.prototype.includes(): 此方法用于判断一个字符串是否包含在另一个字符串中,返回 true 或 false。它是实现模糊匹配(即部分匹配)的关键。
  • 逻辑或运算符 (||): 当需要在一个搜索关键词匹配多个字段中的任意一个时,可以使用 || 运算符连接多个条件。

2. 现有实现与优化点分析

原始代码展示了一个基于mat-table的用户列表,并实现了一个简单的单字段(lastName)过滤功能。

原始HTML片段:

<input type="text" [(ngModel)]="lastname" (input)="Search()"/>
<mat-table [dataSource]="usuarios">
    <!-- ... 省略其他列定义 ... -->
    <ng-container matColumnDef="firstName">
      <mat-header-cell *matHeaderCellDef> Nome </mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.firstName }}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="lastName">
      <mat-header-cell *matHeaderCellDef>Sobrenome</mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.lastName }}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="username">
        <mat-header-cell *matHeaderCellDef>Username</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.username }}</mat-cell>
      </ng-container>
      <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>

原始TypeScript片段:

export class GerenciamentoUsuariosListaComponent implements OnInit {
  @Input() usuarios: any[] = []; // 显示的数据源
  usuarios1: any; // 似乎用于临时存储,但未充分利用
  lastname :string; // 搜索关键词,仅用于姓氏

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

  constructor(private service: GerenciamentoUsuariosService) {
    this.lastname = '';
  }

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

  refreshListUser1() {
    this.usuarios1 = this.service.list().subscribe(
      resp => {
        this.usuarios = resp.content // 直接赋值给显示数据源
       console.log(this.usuarios)
      });
  }

  Search(){
    if(this.lastname != ""){
      this.usuarios = this.usuarios.filter(res =>{
        return res.lastName.toLocaleLowerCase().match(this.lastname.toLocaleLowerCase());
      })
    }else if(this.lastname == ""){
      this.ngOnInit(); // 问题:清空搜索词时会重新加载数据
    }
  }
}

现有实现存在以下优化点:

  1. 单字段限制: Search() 方法目前只针对 lastName 字段进行过滤,无法满足多字段(firstName, username, email)的搜索需求。
  2. 数据源管理: 当搜索词为空时,Search() 方法会调用 ngOnInit() 重新获取数据。这会导致不必要的网络请求,并且在用户频繁清空搜索词时影响性能和用户体验。更优的做法是维护一份原始的完整数据列表,在需要重置过滤时直接使用这份数据。
  3. 变量命名: lastname 变量名不够通用,当实现多字段搜索时,应使用更具描述性的名称,如 searchTerm。
  4. 过滤逻辑: match() 方法通常用于正则表达式匹配,对于简单的字符串包含判断,includes() 方法更为直观和高效。

3. 实现多字段过滤的步骤

我们将对上述代码进行改进,以实现高效的多字段模糊搜索。

3.1 步骤一:更新HTML模板

首先,我们将搜索输入框的 [(ngModel)] 绑定到一个更通用的变量 searchTerm。

<input type="text" [(ngModel)]="searchTerm" (input)="Search()" placeholder="搜索姓名、邮箱或用户名"/>

<mat-table [dataSource]="usuarios">
    <!-- Name Column -->
    <ng-container matColumnDef="firstName">
      <mat-header-cell *matHeaderCellDef> 姓名 </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>姓氏</mat-header-cell>
      <mat-cell *matCellDef="let element">{{ element.lastName }}</mat-cell>
    </ng-container>
    <!-- UserName Column -->
    <ng-container matColumnDef="username">
        <mat-header-cell *matHeaderCellDef>用户名</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.username }}</mat-cell>
      </ng-container>
      <!-- Email Column -->
      <ng-container matColumnDef="email">
        <mat-header-cell *matHeaderCellDef>电子邮件</mat-header-cell>
        <mat-cell *matCellDef="let element">{{ element.email }}</mat-cell>
      </ng-container>
      <!-- ... 其他列和操作按钮 ... -->
</mat-table>

3.2 步骤二:调整组件逻辑 (TypeScript)

在组件中,我们将引入一个新数组 originalUsuarios 来存储从后端获取的完整用户列表。usuarios 数组将始终用于显示过滤后的结果。

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.scss']
})
export class GerenciamentoUsuariosListaComponent implements OnInit {
  @Input() usuarios: any[] = []; // 用于显示和过滤的数据列表
  originalUsuarios: any[] = []; // 存储原始的完整数据列表
  searchTerm: string = ''; // 通用的搜索关键词

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

  constructor(private service: GerenciamentoUsuariosService) { }

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

  refreshListUser1(): void {
    this.service.list().subscribe(
      resp => {
        this.originalUsuarios = resp.content; // 将完整数据存储到 originalUsuarios
        this.usuarios = [...this.originalUsuarios]; // 初始化显示列表为完整数据
        console.log(this.usuarios);
      },
      error => {
        console.error('获取用户列表失败:', error);
        // 处理错误,例如显示错误消息给用户
      }
    );
  }

  Search(): void {
    const keyword = this.searchTerm.toLocaleLowerCase().trim(); // 获取并转换为小写,去除首尾空格

    if (keyword) {
      // 如果有搜索关键词,则从原始数据中过滤
      this.usuarios = this.originalUsuarios.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.originalUsuarios];
    }
  }
}

代码解释:

Java Maven Code Review
Java Maven Code Review

审查Java Maven项目(ZIP压缩包或GitLab仓库URL),检查代码规范、命名、模块边界、可维护性问题以及重复代码。

下载
  1. originalUsuarios: any[] = [];: 新增一个数组用于存储从后端获取的未过滤的完整用户列表。
  2. searchTerm: string = '';: 将 lastname 变量重命名为 searchTerm,使其更通用。
  3. refreshListUser1() 方法修改:
    • 在订阅数据后,首先将 resp.content 赋值给 this.originalUsuarios,确保我们始终有一份完整的数据副本。
    • 然后,使用 this.usuarios = [...this.originalUsuarios]; 将显示列表初始化为完整数据。使用扩展运算符 ... 创建一个副本,以避免直接引用导致意外修改 originalUsuarios。
  4. Search() 方法修改:
    • const keyword = this.searchTerm.toLocaleLowerCase().trim();: 获取搜索词,转换为小写,并使用 trim() 移除可能存在的空白字符,提高搜索准确性。
    • if (keyword): 判断搜索词是否非空。
      • 如果非空: this.usuarios = this.originalUsuarios.filter(...)。这里是关键:我们总是从 originalUsuarios (完整数据)开始过滤,而不是从当前 usuarios (可能已经过滤过的数据)过滤。这确保了每次搜索都是基于完整数据集。过滤条件使用 || 连接多个字段的 includes() 方法,实现了多字段的模糊匹配。
      • 如果为空: this.usuarios = [...this.originalUsuarios];。将显示列表重置为原始的完整用户列表,避免了重新请求数据。

4. 注意事项与进阶考量

  • 性能优化 (去抖/Debounce): 对于包含大量数据或用户输入非常频繁的场景,input 事件可能触发 Search() 方法过于频繁。可以考虑使用 RxJS 的 debounceTime 操作符来延迟 Search() 方法的执行,例如:

    import { Subject } from 'rxjs';
    import { debounceTime } from 'rxjs/operators';
    
    export class GerenciamentoUsuariosListaComponent implements OnInit, OnDestroy {
      // ... 其他变量 ...
      private searchTerms = new Subject<string>();
      private destroy$ = new Subject<void>(); // 用于管理订阅的生命周期
    
      constructor(private service: GerenciamentoUsuariosService) { }
    
      ngOnInit(): void {
        this.refreshListUser1();
    
        this.searchTerms.pipe(
          debounceTime(300), // 300毫秒内没有新输入则执行
          takeUntil(this.destroy$) // 组件销毁时取消订阅
        ).subscribe(() => {
          this.Search();
        });
      }
    
      // 在HTML中调用这个方法
      onSearchInput(): void {
        this.searchTerms.next(this.searchTerm);
      }
    
      ngOnDestroy(): void {
        this.destroy$.next();
        this.destroy$.complete();
      }
    
      // ... Search() 方法保持不变 ...
    }

    HTML中将 (input)="Search()" 改为 (input)="onSearchInput()"。

  • 可扩展性: 如果需要过滤的字段非常多,或者过滤条件需要动态配置,可以考虑将过滤逻辑抽象成一个独立的函数或服务,甚至使用第三方库(如 lodash 的 filter 或自定义管道 Pipe)。

  • 后端过滤: 对于非常大的数据集(例如数万条甚至更多),前端进行过滤可能会导致性能瓶颈。在这种情况下,更推荐将过滤逻辑推送到后端API实现,前端只负责发送搜索关键词并接收过滤后的数据。

  • 用户体验: 考虑在数据加载或过滤时显示加载指示器(如 mat-spinner),并在没有搜索结果时显示友好的提示信息。

  • 完全匹配 vs. 模糊匹配: 当前实现是模糊匹配 (includes())。如果需要完全匹配,可以将 includes(keyword) 替换为 === keyword。

5. 总结

通过本教程,我们学习了如何在Angular项目中实现一个健壮且高效的多字段模糊搜索功能。关键在于:

  1. 维护原始数据副本: 确保在组件中始终有一份完整的、未过滤的数据源,以便进行重置和新的过滤操作。
  2. 利用JavaScript数组和字符串方法: 熟练运用 filter(), toLocaleLowerCase(), includes() 以及逻辑或运算符 || 来构建灵活的过滤条件。
  3. 优化搜索逻辑: 避免不必要的网络请求,并考虑性能优化(如去抖)来提升用户体验。

掌握这些技巧,您将能够为您的Angular应用构建出更加强大和用户友好的数据列表过滤功能。

热门AI工具

更多
Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

272

2026.02.13

TypeScript全栈项目架构与接口规范设计
TypeScript全栈项目架构与接口规范设计

本专题面向全栈开发者,系统讲解基于 TypeScript 构建前后端统一技术栈的工程化实践。内容涵盖项目分层设计、接口协议规范、类型共享机制、错误码体系设计、接口自动化生成与文档维护方案。通过完整项目示例,帮助开发者构建结构清晰、类型安全、易维护的现代全栈应用架构。

480

2026.02.25

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

331

2026.03.13

TypeScript 全栈开发进阶指南
TypeScript 全栈开发进阶指南

面向有 JavaScript 基础的开发者,深入讲解 TypeScript 的类型系统与全栈开发实践。

246

2026.06.03

TypeScript Node.js 全栈工程化与Monorepo架构实践
TypeScript Node.js 全栈工程化与Monorepo架构实践

本专题围绕 TypeScript 在 Node.js 全栈开发中的工程化实践展开,系统讲解 Monorepo 架构设计、包管理策略、模块复用机制以及服务端与前端统一类型系统的构建方法。通过真实项目案例,帮助开发者提升大型全栈项目的可维护性与协作效率。

498

2026.06.16

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

3936

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

2461

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

6702

2023.07.05

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

20

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 5.8万人学习

CSS教程
CSS教程

共754课时 | 95.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn