JavaScript/CSS 列表搜索功能
JavaScript 和 CSS 实现列表搜索功能
列表搜索功能是一种常见的网页交互效果:用户在搜索框中输入关键词,页面上的列表项会实时过滤,只显示匹配的内容。下面我将基于标准的前端技术,提供一个简单的纯 JavaScript 和 CSS 实现方案。这个方案不依赖任何框架,易于理解和扩展。
实现思路
- HTML 结构:一个输入框(用于搜索)和一个无序列表(
<ul>
),列表项(<li>
)包含可搜索的文本。 - CSS 样式:美化搜索框和列表,使其简洁美观。搜索框添加搜索图标背景,列表项添加 hover 效果。
- JavaScript 逻辑:
- 监听输入框的
input
事件(实时响应)。 - 获取搜索关键词,转为小写(忽略大小写)。
- 遍历列表项,检查每个项的文本是否包含关键词(使用
indexOf
方法)。 - 如果匹配,显示该项(
display: block
);否则隐藏(display: none
)。
- 扩展性:可以添加高亮匹配文本的功能,或支持正则表达式匹配。
完整代码示例
以下是完整的 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
属性替换循环过滤。
这个实现参考了菜鸟教程的经典示例,并添加了高亮和优化。 如果需要更复杂的版本(如带分页或后端搜索),可以提供更多细节!