如何使用RxJS实现对象数组的搜索结果展示功能?
使用RxJS实现游戏列表的名称搜索过滤
要实现基于RxJS的游戏名称搜索过滤,核心思路是合并搜索输入流与游戏数据加载流,通过响应式的方式处理过滤逻辑,避免手动操作DOM和事件监听的繁琐。以下是修改后的完整代码及关键说明:
完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Game Search</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.8.0/rxjs.umd.min.js" integrity="sha512-v0/YVjBcbjLN6scjmmJN+h86koeB7JhY4/2YeyA5l+rTdtKLv0VbDBNJ32rxJpsaW1QGMd1Z16lsLOSGI38Rbg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> </head> <body> <h1>Games</h1> <input type="text" id="search_game" placeholder="Search games by name"> <table cellpadding="10"> <thead> <tr> <th style="text-align:left;">Name</th> <th style="text-align:left;">Released</th> <th style="text-align:left;">Genre</th> </tr> </thead> <tbody id="table-content"></tbody> </table> <script> const { fromEvent, ajax, operators: { startWith, debounceTime, map, combineLatest } } = rxjs; // 获取DOM元素 const searchInput = document.getElementById('search_game'); const tableContent = document.getElementById('table-content'); // 1. 创建搜索输入流:提取输入值+防抖+初始空字符串 const search$ = fromEvent(searchInput, 'input').pipe( map(event => event.target.value.trim().toLowerCase()), debounceTime(300), // 防抖300ms,避免频繁触发 startWith('') // 初始值为空,加载数据后显示全部游戏 ); // 2. 创建游戏数据流:获取API数据并处理日期显示逻辑 const games$ = ajax.getJSON('https://api.sampleapis.com/switch/games').pipe( map(gamesList => gamesList.map(game => { // 修复日期显示逻辑:优先显示日本,其次欧洲,最后澳大利亚 let releaseDate = 'N/A'; if (game.releaseDates?.Japan) { releaseDate = `${game.releaseDates.Japan} (Japan)`; } else if (game.releaseDates?.Europe) { releaseDate = `${game.releaseDates.Europe} (Europe)`; } else if (game.releaseDates?.Australia) { releaseDate = `${game.releaseDates.Australia} (Australia)`; } return { ...game, displayDate: releaseDate }; })) ); // 3. 合并两个流:每次搜索变化或数据加载完成时,执行过滤 combineLatest([search$, games$]).pipe( map(([searchTerm, gamesList]) => { // 根据搜索关键词过滤游戏(不区分大小写) return gamesList.filter(game => game.name.toLowerCase().includes(searchTerm) ); }) ).subscribe(filteredGames => { // 渲染过滤后的表格内容 let html = ''; filteredGames.forEach(game => { html += ` <tr> <td>${game.name}</td> <td>${game.displayDate}</td> <td>${game.genre}</td> </tr> `; }); tableContent.innerHTML = html; }); </script> </body> </html>
关键实现说明
搜索流处理:
- 用
fromEvent监听输入框的input事件,提取输入值并转为小写(统一匹配规则)。 debounceTime(300):防抖300毫秒,避免用户每输入一个字符就触发一次过滤,提升性能。startWith(''):给搜索流设置初始空值,确保游戏数据加载完成后自动显示全部内容。
- 用
游戏数据流处理:
- 修复了原代码中日期显示的逻辑错误:优先判断日本日期是否存在,依次 fallback 到欧洲、澳大利亚,避免三目运算符的逻辑混乱。
- 用
map预处理游戏数据,添加displayDate字段,后续渲染时直接使用,简化代码。
合并与过滤:
combineLatest([search$, games$]):合并搜索流和游戏数据流,只有当两个流都发出值后(数据加载完成+搜索输入变化),才会触发后续逻辑。- 过滤逻辑:将游戏名称转为小写后,判断是否包含搜索关键词,实现不区分大小写的模糊匹配。
渲染逻辑:
- 每次过滤完成后,重新生成表格HTML并更新DOM,确保页面内容实时响应搜索输入。
内容的提问来源于stack exchange,提问作者Coder_7
相关产品推荐
相关产品推荐

