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

如何为带搜索功能的下拉菜单创建可搜索分组?

解决下拉菜单分类搜索的匹配逻辑问题

我懂你的痛点——现在的搜索逻辑只盯着单个<li>的文本内容匹配,完全没考虑列表项所属的分类分组对吧?结果就是搜分类关键词时,只有标题<li>能显示,同分类下的其他对象因为文本里没带分类名就被藏起来;要是搜个没匹配到的内容,整个菜单直接空了,体验特别差。

咱们一步步调整,让搜索逻辑贴合你的需求:

第一步:给列表项绑定分类标识

先给每个属于分类的对象<li>加个data-category属性,把它和对应的分类标题关联起来,分类标题单独加个category-header类方便区分。示例HTML结构如下:

<div class="dropdown">
  <input type="text" id="searchInput" placeholder="搜索分类或对象...">
  <ul class="dropdown-menu">
    <li class="category-header">电子产品</li>
    <li data-category="电子产品">手机</li>
    <li data-category="电子产品">笔记本电脑</li>
    <li class="category-header">家居用品</li>
    <li data-category="家居用品">沙发</li>
    <li data-category="家居用品">茶几</li>
  </ul>
</div>

第二步:重写搜索逻辑

原来的搜索只是简单检查每个<li>的文本是否包含关键词,现在要改成:

  • 搜分类名时,显示该分类的标题+所有下属对象
  • 搜对象名时,显示该对象+它所属的分类标题
  • 空搜索时显示全部内容
  • 无匹配时显示提示,而非全隐藏

修改后的JS代码如下:

const input = document.getElementById('searchInput');
const menu = document.querySelector('.dropdown-menu');
const categoryHeaders = menu.querySelectorAll('.category-header');
const itemElements = menu.querySelectorAll('li:not(.category-header)');

input.addEventListener('input', function() {
  const searchTerm = this.value.trim().toLowerCase();
  
  // 搜索框为空时,直接显示所有内容
  if (!searchTerm) {
    categoryHeaders.forEach(header => header.style.display = 'block');
    itemElements.forEach(item => item.style.display = 'block');
    // 移除无结果提示
    const noResult = menu.querySelector('.no-result');
    if (noResult) noResult.remove();
    return;
  }

  // 先隐藏所有内容,准备筛选
  categoryHeaders.forEach(header => header.style.display = 'none');
  itemElements.forEach(item => item.style.display = 'none');

  // 用Set存需要显示的分类,避免重复
  const categoriesToShow = new Set();

  // 遍历所有对象,检查是否匹配关键词或所属分类匹配
  itemElements.forEach(item => {
    const itemText = item.textContent.toLowerCase();
    const itemCategory = item.dataset.category.toLowerCase();
    
    if (itemText.includes(searchTerm) || itemCategory.includes(searchTerm)) {
      item.style.display = 'block';
      categoriesToShow.add(item.dataset.category);
    }
  });

  // 显示需要展示的分类标题
  categoryHeaders.forEach(header => {
    const headerText = header.textContent;
    if (categoriesToShow.has(headerText) || headerText.toLowerCase().includes(searchTerm)) {
      header.style.display = 'block';
    }
  });

  // 处理无匹配的情况:显示提示
  const visibleItems = menu.querySelectorAll('li[style="display: block;"]');
  if (visibleItems.length === 0) {
    let noResult = menu.querySelector('.no-result');
    if (!noResult) {
      noResult = document.createElement('li');
      noResult.className = 'no-result';
      noResult.textContent = '没有找到匹配的内容';
      menu.appendChild(noResult);
    }
    noResult.style.display = 'block';
  } else {
    // 有匹配就移除提示
    const noResult = menu.querySelector('.no-result');
    if (noResult) noResult.remove();
  }
});

第三步:(可选)优化样式区分分类和对象

给分类标题加个样式,让用户一眼就能区分分类和普通对象:

.category-header {
  font-weight: 600;
  color: #555;
  padding: 4px 8px;
  cursor: default;
}
.no-result {
  color: #999;
  font-style: italic;
  padding: 4px 8px;
}
.dropdown-menu li {
  padding: 4px 8px;
  cursor: pointer;
}

这样调整后,搜“电子产品”时,分类标题和下面的手机、笔记本都会显示;搜“手机”时,手机和它的分类标题也会一起出来;要是搜个完全没匹配的词,菜单里会显示“没有找到匹配的内容”,再也不会全空啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:51:32