You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular2的ngFor中实现数据列表的过滤功能

在Angular 2中用ngFor实现查询过滤JSON数组

嘿,这个需求在Angular 2里其实很好实现,我给你拆解成几个清晰的步骤,你跟着做就行:

1. 组件内准备数据和过滤逻辑

首先在你的组件类里,定义好原始的JSON数据数组,再声明一个用来绑定搜索输入框的变量,最后写一个getter方法来返回过滤后的结果——用getter的好处是,每次搜索关键词变化时,它会自动重新计算过滤后的数组,不用手动触发更新:

import { Component } from '@angular/core';

@Component({
  selector: 'app-filter-list',
  templateUrl: './filter-list.component.html'
})
export class FilterListComponent {
  // 替换成你自己的JSON数据数组
  originalData = [
    { id: 1, name: 'Angular入门指南', category: '前端' },
    { id: 2, name: 'TypeScript进阶', category: '前端' },
    { id: 3, name: 'Node.js基础', category: '后端' }
  ];
  // 绑定搜索输入框的变量
  searchQuery = '';

  // 获取过滤后数据的getter
  get filteredData() {
    // 如果搜索框为空,直接返回全部数据
    if (!this.searchQuery.trim()) {
      return this.originalData;
    }
    // 按名称和分类过滤,你可以根据自己的需求调整过滤字段
    const lowerCaseQuery = this.searchQuery.toLowerCase();
    return this.originalData.filter(item => 
      item.name.toLowerCase().includes(lowerCaseQuery) ||
      item.category.toLowerCase().includes(lowerCaseQuery)
    );
  }
}

2. 模板中用ngFor渲染过滤后的列表

接下来在组件的HTML模板里,先添加一个绑定了searchQuery的输入框,然后用*ngFor遍历filteredData即可:

<!-- 搜索输入框 -->
<input type="text" [(ngModel)]="searchQuery" placeholder="搜索名称或分类...">

<!-- 渲染过滤后的列表 -->
<ul>
  <li *ngFor="let item of filteredData">
    {{ item.name }} ({{ item.category }})
  </li>
</ul>

⚠️ 注意:因为用到了[(ngModel)]双向绑定,你需要确保在对应的模块(比如AppModule)里导入了FormsModule:

import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [
    // 其他必要模块
    FormsModule
  ]
})
export class AppModule { }

3. 进阶优化(可选)

如果你的数据量比较大,或者想提升用户体验,可以考虑下面两个优化点:

防抖处理

避免用户每输入一个字符就触发一次过滤,用RxJS的debounceTime来延迟触发过滤操作:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

@Component({
  selector: 'app-filter-list',
  templateUrl: './filter-list.component.html'
})
export class FilterListComponent implements OnInit, OnDestroy {
  originalData = [/* 你的数据 */];
  searchQuery = '';
  private searchSubject = new Subject<string>();
  filteredData = [...this.originalData];
  private subscription;

  ngOnInit() {
    this.subscription = this.searchSubject.pipe(
      debounceTime(300), // 300ms内没有新输入才触发过滤
      distinctUntilChanged() // 只有搜索内容真正变化时才触发
    ).subscribe(query => {
      const lowerCaseQuery = query.toLowerCase();
      this.filteredData = this.originalData.filter(item => 
        item.name.toLowerCase().includes(lowerCaseQuery) ||
        item.category.toLowerCase().includes(lowerCaseQuery)
      );
    });
  }

  onSearchInput() {
    this.searchSubject.next(this.searchQuery);
  }

  // 组件销毁时取消订阅,避免内存泄漏
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

对应的模板输入框要改成:

<input type="text" [(ngModel)]="searchQuery" (input)="onSearchInput()" placeholder="搜索名称或分类...">

封装过滤管道

如果过滤逻辑需要在多个组件复用,可以把它封装成一个自定义管道:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
  // items: 要过滤的数组; query: 搜索关键词; fields: 需要匹配的字段数组
  transform(items: any[], query: string, fields: string[]): any[] {
    if (!items || !query) {
      return items;
    }
    const lowerCaseQuery = query.toLowerCase();
    return items.filter(item => 
      fields.some(field => item[field].toLowerCase().includes(lowerCaseQuery))
    );
  }
}

然后在模块里声明这个管道,模板里就可以这样用:

<input type="text" [(ngModel)]="searchQuery" placeholder="搜索...">

<ul>
  <li *ngFor="let item of originalData | filter: searchQuery: ['name', 'category']">
    {{ item.name }} ({{ item.category }})
  </li>
</ul>

⚠️ 小提示:Angular默认的管道是纯管道,只有当输入的引用变化时才会重新计算。如果你的原始数据是动态加载的,可能需要把管道设置为不纯管道(pure: false),但要注意这会增加性能开销,因为它会在每个变更检测周期都运行。

内容的提问来源于stack exchange,提问作者mahendra Tripathy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:16:14