
本文介绍如何使用原生 javascript 为静态产品列表添加动态分组筛选功能:通过为每个列表项添加 data-group 属性,自动生成对应分组的复选框控件,并利用 classlist.toggle 实现点击切换显示/隐藏,无需重新渲染 dom。
本文介绍如何使用原生 javascript 为静态产品列表添加动态分组筛选功能:通过为每个列表项添加 data-group 属性,自动生成对应分组的复选框控件,并利用 classlist.toggle 实现点击切换显示/隐藏,无需重新渲染 dom。
在构建商品展示页时,常需支持用户按品类(如“热饮”“冷饮”)快速筛选内容。相比每次点击都重新生成整个列表,更高效的做法是一次性渲染全部数据,再通过 CSS 类控制显隐——这既提升性能,又保证交互流畅。
✅ 核心实现步骤
-
标记分组信息:在创建 <li> 元素时,将 item.group 写入 data-group 属性,便于后续选择器定位:
li.dataset.group = item.group;
-
动态生成筛选控件:遍历 products 提取所有唯一分组(使用 new Set() 去重),为每个分组创建一个带 name 的复选框(<input type="checkbox">)和对应标签:
const allGroups = [...new Set(products.map(p => p.group))]; allGroups.forEach(group => { const cb = document.createElement('input'); cb.name = group; cb.type = 'checkbox'; cb.checked = true; // 默认显示该组 cb.onchange = onCheckboxToggle; element.appendChild(cb); const label = document.createElement('label'); label.textContent = group; label.htmlFor = group; // 注意:正确属性名为 htmlFor,非 for element.appendChild(label); }); -
绑定筛选逻辑:当复选框状态改变时,查找所有 data-group 匹配的 <li> 元素,并切换 .hide 类:
立即学习“Java免费学习笔记(深入)”;
const onCheckboxToggle = (e) => { const group = e.target.name; const items = document.querySelectorAll(`li[data-group="${group}"]`); items.forEach(item => item.classList.toggle('hide')); };
? 完整可运行代码示例
<!DOCTYPE html>
<html>
<head>
<style>
.hide { display: none; }
#filterControls { margin-bottom: 1rem; }
#filterControls label { margin-right: 1em; }
</style>
</head>
<body>
<div id="filterControls"></div>
<ul id="productList"></ul>
<script>
const products = [
{ name: 'koffie', price: 2.50, group: 'warme dranken' },
{ name: 'thee', price: 2.50, group: 'warme dranken' },
{ name: 'cola', price: 3.50, group: 'koude dranken' },
{ name: 'ice tea', price: 3.50, group: 'koude dranken' },
{ name: 'patat', price: 3.50, group: 'friet' },
{ name: 'patat mayo', price: 3.50, group: 'friet' },
{ name: 'frikandel', price: 3.50, group: 'snacks' },
{ name: 'kroket', price: 3.50, group: 'snacks' }
];
const list = document.querySelector('#productList');
const filterContainer = document.querySelector('#filterControls');
const addProducts = (array, element) => {
array.forEach(item => {
const li = document.createElement('li');
li.textContent = `${item.name} — €${item.price}`;
li.dataset.group = item.group;
element.appendChild(li);
});
};
const addGroupBoxes = (array, container) => {
const groups = [...new Set(array.map(p => p.group))];
groups.forEach(group => {
const cb = document.createElement('input');
cb.type = 'checkbox';
cb.name = group;
cb.checked = true;
cb.onchange = onCheckboxToggle;
const label = document.createElement('label');
label.textContent = group;
label.htmlFor = group;
container.append(cb, label, ' ');
});
};
const onCheckboxToggle = (e) => {
const group = e.target.name;
document.querySelectorAll(`li[data-group="${group}"]`)
.forEach(el => el.classList.toggle('hide'));
};
// 初始化渲染
addProducts(products, list);
addGroupBoxes(products, filterContainer);
</script>
</body>
</html>⚠️ 注意事项与优化建议
- label.for 应写作 label.htmlFor:HTML 属性 for 在 DOM API 中映射为 htmlFor(因 for 是 JavaScript 保留字);
- 避免重复渲染:本方案不调用 filter() 重建数组或重写 innerHTML,而是纯 CSS 控制可见性,响应更快、无闪烁;
- 无障碍友好:为每个复选框添加 <label> 并关联 htmlFor,确保屏幕阅读器可识别;
- 扩展性提示:若需支持多条件组合筛选(如“热饮 + 小于 €3”),可在 onCheckboxToggle 中收集所有已勾选分组,再用 querySelectorAll 拼接多个 [data-group="xxx"] 选择器,或改用 Array.from(...).filter() 配合 classList.contains() 动态判断。
此方法轻量、语义清晰、兼容性强,适用于中小型静态数据筛选场景,是原生 JavaScript 前端过滤的经典实践。


















