
本文介绍一种纯前端 JavaScript 实现方案,通过解析 data-* 属性中的空格分隔多值,并结合用户勾选的多个筛选条件,精准显示同时满足所有已选条件的产品项,无需服务端参与。
本文介绍一种纯前端 javascript 实现方案,通过解析 `data-*` 属性中的空格分隔多值,并结合用户勾选的多个筛选条件,精准显示同时满足所有已选条件的产品项,无需服务端参与。
在构建产品对比页时,常需支持多维度、多值的组合筛选(如颜色支持“red white blue”,尺寸支持“small medium”等),而 HTML 的 data-* 属性天然适合存储这类结构化元数据。关键在于:每个产品项必须同时满足所有当前被勾选的筛选项,才予以显示——即采用“与(AND)逻辑”,而非“或(OR)逻辑”。
✅ 核心实现思路
- 统一监听所有复选框变化:使用事件委托监听 .products 外层容器或 document 上的 change 事件;
- 按类型归类已选值:遍历所有 input[type="checkbox"]:checked,按 data-filter-type(如 "color"、"size")分组,收集各维度的选中值数组;
- 逐个校验产品项:对每个 .productItem,检查其每个 data-* 属性值(如 data-color="red white blue")是否包含该维度下所有已选值;
- 严格匹配(AND 逻辑):若某维度存在已选值,但当前产品项的对应 data-* 值中不包含其中任意一个,则隐藏该产品项。
⚠️ 注意:data-power="battery" 与 data-power="inductive battery" 是不同的字符串;需将后者拆分为数组 ['inductive', 'battery'] 后用 includes() 判断。
? 完整可运行代码示例
<script>
function applyFilters() {
// 步骤1:按 filter-type 归类所有已选值
const selections = {};
document.querySelectorAll('input[type="checkbox"][data-filter-type]:checked').forEach(cb => {
const type = cb.dataset.filterType;
const value = cb.value;
if (!selections[type]) selections[type] = [];
selections[type].push(value);
});
// 步骤2:遍历所有产品项
document.querySelectorAll('.productItem').forEach(item => {
let show = true;
// 对每个筛选维度,验证是否全部满足
for (const [type, values] of Object.entries(selections)) {
if (values.length === 0) continue;
const dataAttr = `data-${type}`;
const itemData = item.getAttribute(dataAttr);
if (!itemData) {
show = false;
break;
}
// 将 data 属性值按空格分割为数组(兼容多值)
const itemValues = itemData.trim().split(/\s+/);
// 检查当前维度所有选中值是否都存在于 itemValues 中
for (const val of values) {
if (!itemValues.includes(val)) {
show = false;
break;
}
}
if (!show) break;
}
// 应用显隐
item.style.display = show ? '' : 'none';
});
}
// 步骤3:绑定事件(支持动态添加的 checkbox)
document.addEventListener('change', e => {
if (e.target.type === 'checkbox' && e.target.hasAttribute('data-filter-type')) {
applyFilters();
}
});
// 初始化:首次加载时执行一次
document.addEventListener('DOMContentLoaded', applyFilters);
</script>? 使用说明与注意事项
- ✅ *多值 `data-属性格式规范**:确保data-color="red white blue"等属性值使用**单个空格分隔**,无前导/尾随空格,避免split(' ')` 出现空字符串;
- ✅ 大小写敏感:"Battery" ≠ "battery",建议统一使用小写存储与比对;
- ⚠️ 性能提示:对于超百级产品项,可考虑节流(throttle)change 事件,或使用 DocumentFragment 批量操作 DOM;
- ✅ 无障碍友好:保留原生 <label> 结构,支持键盘导航与屏幕阅读器;
- ? 扩展性强:新增筛选维度(如 data-brand)只需添加对应 data-filter-type="brand" 的复选框,无需修改 JS 逻辑。
该方案完全运行于客户端,零服务端依赖,响应迅速,语义清晰,是构建轻量级产品对比页的理想实践。

















