新闻中心
构建原生JS搜索过滤器:添加“无匹配项”提示

本教程详细指导如何使用原生j*ascript构建一个高效的搜索过滤器,并集成“无匹配项”提示功能。文章将涵盖html结构、css样式优化(强调`display: none`的优势),以及核心j*ascript逻辑,包括事件监听、元素过滤和根据搜索结果动态显示/隐藏提示信息。通过具体代码示例和最佳实践,帮助开发者提升用户体验。
在现代网页应用中,搜索过滤功能是提升用户体验的关键一环。当用户输入搜索词却没有找到任何匹配项时,一个清晰的“无匹配项”提示能有效避免用户困惑。本教程将详细介绍如何使用原生J*aScript实现一个带有此类提示的搜索过滤器。
1. HTML结构设计
首先,我们需要定义页面的基本HTML结构,包括搜索输入框、待过滤的卡片列表,以及用于显示“无匹配项”信息的段落。
<section id="seccion-diez" class="section">
<h2 data-dark>搜索过滤器</h2>
<!-- 搜索输入框,用于用户输入搜索词 -->
<input type="search" name="busqueda" placeholder="搜索..." class="card-filter">
<!-- 无匹配项提示信息,初始状态为隐藏 -->
<p class="hidden" id="mensaje">未找到匹配结果</p>
<!-- 待过滤的卡片容器 -->
<article class="contenedor-cards">
<!-- 示例卡片项 -->
<figure class="card">
@@##@@
<figcaption>自然</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>随机</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>科技</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>人物</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>动物</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>建筑</figcaption>
</figure>
</article>
</section>关键点:
- input 元素:带有 card-filter 类,作为搜索事件的触发器。
- p 元素:带有 id="mensaje" 和 class="hidden",用于显示或隐藏“无匹配项”提示。
- figure.card 元素:代表每个可过滤的项,其 figcaption 文本将用于匹配搜索词。
2. CSS样式定义
为了实现元素的隐藏和显示,我们定义一个 .hidden 类。这里,我们推荐使用 display: none; 而非 visibility: hidden;。
.hidden {
display: none; /* 元素将从文档流中完全移除,不占据任何空间 */
opacity: 0; /* 配合 display: none 使用,虽然不影响布局,但可用于平滑过渡(如果结合JS移除display:none) */
order: 1; /* 弹性盒或网格布局中的排序属性,这里作为
示例保留 */
}注意事项:display: none 与 visibility: hidden 的区别
- display: none;:元素将从文档流中完全移除,不占据任何空间,且不会响应任何事件。这是隐藏元素最彻底的方式,适用于需要完全移除元素及其对布局影响的场景。
- visibility: hidden;:元素仍然占据其原有的空间,只是在视觉上不可见,但仍然会影响布局。它依然会响应事件。
在本教程的搜索过滤场景中,我们希望隐藏的卡片不占用任何空间,因此 display: none; 是更合适的选择。
Anakin
一站式 AI 应用聚合平台,无代码的AI应用程序构建器
317
查看详情
3. J*aScript核心逻辑实现
J*aScript代码将负责监听搜索框的输入事件,根据输入内容过滤卡片,并根据过滤结果动态显示或隐藏“无匹配项”提示。
const d = document; // 简化 document 引用
/**
* 实现搜索过滤功能,并动态显示“无匹配项”提示。
* @param {string} inputSelector - 搜索输入框的CSS选择器。
* @param {string} cardSelector - 待过滤卡片的CSS选择器。
*/
function filtroBusqueda(inputSelector, cardSelector) {
d.addEventListener("keyup", (e) => {
// 检查事件是否来源于指定的搜索输入框,如果不是则提前返回,避免不必要的处理
if (!e.target.matches(inputSelector)) return;
// 如果按下的是Escape键,清空搜索框内容
if (e.key === "Escape") e.target.value = "";
// 获取所有待过滤的卡片元素
const cards = d.querySelectorAll(cardSelector);
const searchTerm = e.target.value.toLowerCase(); // 获取搜索词并转为小写
// 遍历所有卡片,根据搜索词进行显示或隐藏
cards.forEach((elemento) => {
// 检查卡片文本内容是否包含搜索词
if (elemento.textContent.toLowerCase().includes(searchTerm)) {
elemento.classList.remove("hidden"); // 包含则显示
} else {
elemento.classList.add("hidden"); // 不包含则隐藏
}
});
// 过滤出当前可见的卡片
// 使用 Array.from 或扩展运算符将 NodeList 转换为数组,以便使用 filter 方法
const visibleCards = Array.from(cards).filter(
(elemento) => !elemento.classList.contains("hidden")
);
// 根据可见卡片的数量来显示或隐藏“无匹配项”提示
const messageElement = d.querySelector("#mensaje");
if (visibleCards.length > 0) {
messageElement.classList.add("hidden"); // 有可见卡片,隐藏提示
} else {
messageElement.classList.remove("hidden"); // 没有可见卡片,显示提示
}
});
}
// 当DOM内容完全加载后,初始化搜索过滤器
d.addEventListener("DOMContentLoaded", () => {
filtroBusqueda(".card-filter", ".card");
});代码解析:
- 事件监听 (keyup):当用户在文档中释放键盘按键时触发。我们只关心在搜索输入框中的按键。
- 早期返回 (if (!e.target.matches(inputSelector)) return;):这是一个良好的实践,可以减少不必要的代码执行和嵌套深度,提高代码可读性。
- 清空搜索框 (e.key === "Escape"):用户按下 Escape 键时,清空搜索框内容,方便快速重置搜索。
-
过滤逻辑:
- 获取所有带有 .card 类的元素。
- 将搜索框的值转换为小写 (toLowerCase()),以便进行不区分大小写的匹配。
- 遍历每个卡片,检查其 textContent 是否包含搜索词。
- 如果包含,则移除 .hidden 类(显示卡片);否则,添加 .hidden 类(隐藏卡片)。
-
“无匹配项”提示逻辑:
- 在所有卡片处理完毕后,我们通过 Array.from(cards).filter(...) 筛选出所有当前可见的卡片。
- 如果 visibleCards.length 大于 0,说明至少有一个卡片匹配,此时应隐藏“无匹配项”提示。
- 如果 visibleCards.length 为 0,说明没有卡片匹配,此时应显示“无匹配项”提示。
4. 完整代码示例
将上述HTML、CSS和J*aScript整合,即可实现一个功能完整的搜索过滤器。
index.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>
/* 基础样式,可根据需要调整 */
body { font-family: sans-serif; margin: 20px; }
.contenedor-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-top: 20px;
}
.card {
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
text-align: center;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.card img {
width: 100%;
height: 150px;
object-fit: cover;
}
.card figcaption {
padding: 10px;
font-weight: bold;
}
input[type="search"] {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
#mensaje {
padding: 10px;
background-color: #ffe0b2;
color: #e65100;
border: 1px solid #ff9800;
border-radius: 4px;
text-align: center;
margin-bottom: 15px;
}
/* 隐藏元素的样式 */
.hidden {
display: none;
opacity: 0;
/* order: 1; 仅在flex或grid布局中生效,这里作为示例保留 */
}
</style>
</head>
<body>
<section id="seccion-diez" class="section">
<h2 data-dark>搜索过滤器</h2>
<input type="search" name="busqueda" placeholder="搜索..." class="card-filter">
<p class="hidden" id="mensaje">未找到匹配结果</p>
<article class="contenedor-cards">
<figure class="card">
@@##@@
<figcaption>自然</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>随机</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>科技</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>人物</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>动物</figcaption>
</figure>
<figure class="card">
@@##@@
<figcaption>建筑</figcaption>
</figure>
</article>
</section>
<script>
const d = document;
function filtroBusqueda(inputSelector, cardSelector) {
d.addEventListener("keyup", (e) => {
if (!e.target.matches(inputSelector)) return;
if (e.key === "Escape") e.target.value = "";
const cards = d.querySelectorAll(cardSelector);
const searchTerm = e.target.value.toLowerCase();
cards.forEach((elemento) => {
if (elemento.textContent.toLowerCase().includes(searchTerm)) {
elemento.classList.remove("hidden");
} else {
elemento.classList.add("hidden");
}
});
const visibleCards = Array.from(cards).filter(
(elemento) => !elemento.classList.contains("hidden")
);
const messageElement = d.querySelector("#mensaje");
if (visibleCards.length > 0) {
messageElement.classList.add("hidden");
} else {
messageElement.classList.remove("hidden");
}
});
}
d.addEventListener("DOMContentLoaded", () => {
filtroBusqueda(".card-filter", ".card");
});
</script>
</body>
</html>5. 注意事项与最佳实践
- 语义化HTML:使用 figure 和 figcaption 标签来表示带有标题的图片内容,增强了HTML的语义性。
- CSS类命名:使用清晰的类名如 hidden 能够准确表达其用途。
-
性能优化:
- 对于大型数据集,频繁的DOM操作可能会影响性能。可以考虑使用防抖 (debounce) 技术,限制 keyup 事件的触发频率,例如,在用户停止输入一段时间后才执行过滤。
- 在过滤时,避免在循环内部频繁查询DOM(例如 d.querySelector),应在循环外部一次性获取所有相关元素。
-
可访问性 (Accessibility):
- 对于搜索输入框,可以添加 aria-label 或关联 label 标签,以提高屏幕阅读器用户的体验。
- 当“无匹配项”提示显示时,可以考虑使用 aria-live 区域,以便屏幕阅读器能够自动播报此信息。
- 模块化:在实际项目中,可以将 filtroBusqueda 函数放在单独的J*aScript文件中,并通过 import / export 进行模块化管理,如原始问题中的做法,这有助于代码的组织和维护。
6. 总结
通过本教程,我们学习了如何使用原生J*aScript构建一个功能完善的搜索过滤器,并成功集成了“无匹配项”提示功能。这不仅提升了用户体验,还通过最佳实践(如 display: none 的使用、早期返回语句)优化了代码结构和性能。掌握这些技术将有助于您在前端开发中创建更具交互性和用户友好的界面。
以上就是构建原生JS搜索过滤器:添加“无匹配项”提示的详细内容,更多请关注其它相关文章!
# 浙江职业能力建设网站
# 鼠标
# 遍历
# 提示信息
# 中文网
# 文档
# 按下
# 河南优化产品关键词排名
# 安庆seo推广哪家好
# 清空
# 日照网站建设网站优化
# 如何入围建设网站平台
# 网站建设 技术方案模板
# 培训机构网站推广
# 龙岩网站建设策划书模板
# 东莞百度seo关键词排名技术
# 宣传关键词排名
# css
# 如何使用
# 输入框
# 移除
# cs
# 区别
# ai
# 前端开发
# ssl
# access
# node
# 前端
# js
# html
# java
# javascript
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
PHP中获取MongoDB服务器运行时间(Uptime)的专业指南
Mac怎么使用表情符号_Mac Emoji快捷键面板
优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题
steam官方入口大全 steam账号注册及操作指南
PrimeNG Sidebar背景色自定义指南:CSS覆盖与主题化实践
fishbowl官网免费版 fishbowl养鱼网站入口
Python自定义类排序:解决lambda键值访问TypeError的实践指南
响应式CSS Grid布局:优化网格项在小屏幕下的堆叠与宽度适配
QQ邮箱正确登录入口_QQ邮箱官方网站使用地址
在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用
J*aScript 字符串标签转换:使用正则表达式高效替换
J*a递归快速排序中静态变量导致数据累积问题的解决方案
JUnit5/Mockito:优雅测试内部依赖与异常处理的实践
QQ邮箱网页版快速登录 QQ邮箱邮箱账号官方入口地址
C++如何实现一个装饰器模式_C++设计模式之动态地给对象添加额外职责
探索高级语言到原生C/C++的转译:挑战与内存管理策略
QQ官网正版登录链接 QQ在线登录入口最新
LINQ to XML为何解析失败? 深入理解C# XDocument的异常处理
zookeeper 都有哪些功能?
谷歌学术网站直达地址 谷歌学术搜索网页版一键进入
J*a中实现Go语言select通道多路复用机制
yandex入口引擎手机版 yandex安卓版下载入口
Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐
汽水音乐网页版使用入口_汽水音乐电脑版播放指南
Bing引擎入口最新2025 Bing搜索免费官方登录
Lar*el如何正确地在控制器和模型之间分配逻辑_Lar*el代码职责分离与架构建议
c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学
漫蛙manwa2最新登录网址_漫蛙manwa2手机网页版入口
c++如何使用Catch2编写单元测试_c++简洁易用的BDD风格测试框架
QQ邮箱登录平台入口 QQ邮箱网页版邮箱官方入口
C++编译期如何执行复杂计算_C++模板元编程(TMP)技巧与应用
HTML元素状态管理:根据DIV内容动态启用/禁用按钮
使用J*aScript检测输入元素是否包含在特定类中
可靠CSGO开箱平台解析 CSGO开箱网合集
服务端验证_j*ascript输入检查
126邮箱账号注册 电脑版登录入口
vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧
如何在Python中使用Optional类型处理可变对象并避免Pylint警告
Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址
护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?
taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】
整合Supabase认证与Django模型:跨模式迁移的解决方案
不同用户不同价格! 索尼开启账户个性化定价测试
poki网页游戏推荐_poki免费游戏平台入口
QQ邮箱在线使用入口 QQ邮箱个人账号网页版登录
12306选座怎么选到临时改签座_12306改签选座策略与步骤
outlook中文官网入口地址 outlook官方中文版直达首页链接
QQ邮箱官方登录入口_QQ邮箱网页版快捷使用平台
荒野行动PC版怎么注册_荒野行动PC版账号注册详细流程图文教程
天猫2025双十一0点秒杀攻略 天猫爆款抢购时间


2025-12-12
浏览次数:次
返回列表
示例保留 */
}