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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:56:21