Angular 17中如何用RxJS正确实现Observable的动态过滤?
最优实现方案
核心要解决的就是保留原始数据的同时,跟着用户输入的搜索条件实时过滤结果,既不能改原始数据导致丢内容,还要支持搜索条件动态更新。
第一步:改造TokenService,用双Subject管理状态
把原始数据和搜索条件分开存,通过流的组合实时生成过滤结果:
// ./token.service.ts import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable, combineLatest, map } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class TokenService { // 存原始完整的token数据,只在内部修改 private _rawTokens$ = new BehaviorSubject<Token[]>([]); // 存用户输入的搜索条件,同样只内部更新 private _searchQuery$ = new BehaviorSubject<string>(''); // 对外暴露过滤后的结果流,自动结合原始数据和搜索条件 readonly filteredTokens$: Observable<Token[]>; constructor() { this.getTokens(); // 组合两个流,只要其中一个变化就重新过滤 this.filteredTokens$ = combineLatest([this._rawTokens$, this._searchQuery$]).pipe( map(([tokens, query]) => { if (!query.trim()) return tokens; // 空搜索直接返回全量数据 const lowerQuery = query.toLowerCase(); return tokens.filter(token => token.issuer.toLowerCase().includes(lowerQuery) ); }) ); } // 模拟从接口拿数据,实际替换成你的HTTP请求就行 private getTokens(): void { const mockTokens: Token[] = [ { issuer: 'Work' }, { issuer: 'Test' }, { issuer: 'New' } ]; this._rawTokens$.next(mockTokens); } // 对外提供更新搜索条件的方法 updateSearchQuery(query: string): void { this._searchQuery$.next(query); } }
第二步:组件模板里直接用过滤后的流
不用手动管订阅,靠async管道自动处理:
<!-- 组件模板 --> <input type="text" placeholder="搜索..." (input)="tokenService.updateSearchQuery($event.target.value)" > <ul> <li *ngFor="let token of tokenService.filteredTokens$ | async"> {{ token.issuer }} </li> </ul>
为啥这方案最优?
- 数据不丢:原始数据一直存在
_rawTokens$里,过滤操作不会碰它,不用额外做缓存 - 自动更新:不管是搜索条件变了,还是原始数据(比如从接口新拉了数据)更新了,过滤结果都会自动同步
- 性能高效:只有原始数据或搜索条件变化时才会执行过滤逻辑,不会做无用计算
- 符合RxJS思路:用流的组合实现逻辑,不用手动写一堆订阅、取消订阅的代码,减少bug
内容的提问来源于stack exchange,提问作者mrjonleek
相关产品推荐
相关产品推荐

