|

JavaScript/CSS 列表搜索功能

JavaScript 和 CSS 实现列表搜索功能

列表搜索功能是一种常见的网页交互效果:用户在搜索框中输入关键词,页面上的列表项会实时过滤,只显示匹配的内容。下面我将基于标准的前端技术,提供一个简单的纯 JavaScript 和 CSS 实现方案。这个方案不依赖任何框架,易于理解和扩展。

实现思路

  1. HTML 结构:一个输入框(用于搜索)和一个无序列表(<ul>),列表项(<li>)包含可搜索的文本。
  2. CSS 样式:美化搜索框和列表,使其简洁美观。搜索框添加搜索图标背景,列表项添加 hover 效果。
  3. JavaScript 逻辑
  • 监听输入框的 input 事件(实时响应)。
  • 获取搜索关键词,转为小写(忽略大小写)。
  • 遍历列表项,检查每个项的文本是否包含关键词(使用 indexOf 方法)。
  • 如果匹配,显示该项(display: block);否则隐藏(display: none)。
  1. 扩展性:可以添加高亮匹配文本的功能,或支持正则表达式匹配。

完整代码示例

以下是完整的 HTML、CSS 和 JS 代码。你可以复制到一个 .html 文件中,直接在浏览器中打开测试。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表搜索功能</title>
    <style>
        /* CSS 样式 */
        body {
            font-family: Arial, sans-serif;
            max-width: 400px;
            margin: 50px auto;
            padding: 20px;
        }

        #searchInput {
            background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1LjggMTUuOEMxOC40IDEzLjIgMjEgMTAuMSA1LjIgMTAuMUMxLjkgMTAuMSAwIDExLjkgMCAxNC4yQzAgMTYuNSAxLjkgMTguNCA0LjIgMTguNEM1LjUgMTguNyA2LjkgMTkuMCA4LjMgMTkuMEM5LjcgMTkuMCAxMS4xIDE4LjcgMTIuNCAxOC40TDE1LjggMTUuOFoiLz4KPGNpcmNsZSBjeD0iMTEiIGN5PSIxMSIgcj0iOCIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0ibm9uZSIvPgo8L3N2Zz4K'); /* 内嵌 SVG 搜索图标 */
            background-position: 10px 12px;
            background-repeat: no-repeat;
            background-size: 20px;
            width: 100%;
            font-size: 16px;
            padding: 12px 20px 12px 40px;
            border: 1px solid #ddd;
            border-radius: 4px;
            margin-bottom: 12px;
            box-sizing: border-box;
        }

        #myUL {
            list-style-type: none;
            padding: 0;
            margin: 0;
            border: 1px solid #ddd;
            border-radius: 4px;
            max-height: 300px;
            overflow-y: auto;
        }

        #myUL li {
            padding: 12px;
            border-bottom: 1px solid #eee;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        #myUL li:hover {
            background-color: #f5f5f5;
        }

        #myUL li.hidden {
            display: none;
        }

        /* 匹配高亮(可选扩展) */
        .highlight {
            background-color: yellow;
        }
    </style>
</head>
<body>
    <h2>搜索列表</h2>
    <input type="text" id="searchInput" placeholder="输入关键词搜索...">

    <ul id="myUL">
        <li>Google</li>
        <li>Runoob (菜鸟教程)</li>
        <li>Taobao (淘宝)</li>
        <li>Wiki (维基百科)</li>
        <li>Facebook</li>
        <li>Zhihu (知乎)</li>
        <li>Weibo (微博)</li>
        <li>Tmall (天猫)</li>
    </ul>

    <script>
        // JavaScript 逻辑
        const input = document.getElementById('searchInput');
        const filter = document.getElementById('myUL');
        const li = filter.getElementsByTagName('li');
        let originalText = []; // 存储原始文本,用于高亮恢复

        // 初始化:保存原始文本
        for (let i = 0; i < li.length; i++) {
            originalText[i] = li[i].innerText;
        }

        // 监听输入事件
        input.addEventListener('input', function() {
            const searchTerm = this.value.toLowerCase(); // 转为小写
            let hasVisible = false;

            for (let i = 0; i < li.length; i++) {
                const txtValue = originalText[i].toLowerCase(); // 原始文本小写
                const a = li[i].getElementsByTagName('a')[0]; // 如果有链接

                if (txtValue.indexOf(searchTerm) > -1) { // 包含关键词
                    li[i].style.display = ''; // 显示
                    li[i].classList.remove('hidden');
                    hasVisible = true;

                    // 可选:高亮匹配文本
                    if (searchTerm) {
                        li[i].innerHTML = originalText[i].replace(new RegExp(searchTerm, 'gi'), match => `<span class="highlight">${match}</span>`);
                    } else {
                        li[i].innerHTML = originalText[i]; // 恢复原始
                    }

                    if (a) a.innerHTML = originalText[i]; // 如果是链接,同步
                } else {
                    li[i].style.display = 'none'; // 隐藏
                    li[i].classList.add('hidden');
                }
            }

            // 如果无匹配,显示提示(可选)
            if (!hasVisible) {
                filter.innerHTML = '<li style="padding: 12px; color: #999;">无匹配结果</li>';
            } else if (!searchTerm) {
                // 恢复列表
                for (let i = 0; i < li.length; i++) {
                    li[i].innerHTML = originalText[i];
                    li[i].style.display = '';
                    li[i].classList.remove('hidden');
                }
            }
        });
    </script>
</body>
</html>

代码说明

  • HTML:使用 <input type="search"> 类型(现代浏览器支持),列表用 <ul><li>
  • CSS:搜索框添加了内嵌 SVG 图标(无需外部文件)。列表添加滚动条(overflow-y: auto)和 hover 效果。.hidden 类用于隐藏项。
  • JS
  • input 事件:实时监听用户输入。
  • indexOf:检查是否包含关键词(返回 -1 表示不匹配)。
  • 高亮:使用 replace 和正则表达式(gi 标志忽略大小写、全局匹配)添加黄色背景。
  • 边缘处理:无匹配时显示提示;清空搜索时恢复原列表。
  • 性能:适合小型列表(<1000 项)。大型列表可优化为虚拟滚动。

测试与扩展

  • 测试:打开 HTML 文件,在搜索框输入 “oo”,会过滤出 “Google”、”Runoob” 等。
  • 扩展建议
  • 添加点击事件li[i].addEventListener('click', ...) 跳转链接。
  • 支持多字段搜索:如果列表项有子元素(如姓名、描述),遍历多个 innerText
  • ** debounce 防抖**:输入频繁时延迟执行(使用 setTimeout)。
  • 框架集成:在 Vue/React 中,可用 computed 属性替换循环过滤。

这个实现参考了菜鸟教程的经典示例,并添加了高亮和优化。 如果需要更复杂的版本(如带分页或后端搜索),可以提供更多细节!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注