本文介绍如何使用纯 JavaScript 实现基于多个 data-* 属性(支持空格分隔多值)的实时产品筛选功能,通过监听复选框状态,精准显示同时满足所有已选条件的产品项。
本文介绍如何使用纯 javascript 实现基于多个 `data-*` 属性(支持空格分隔多值)的实时产品筛选功能,通过监听复选框状态,精准显示同时满足所有已选条件的产品项。
在构建产品对比页时,常需让用户从多个维度(如颜色、尺寸、供电方式等)组合筛选商品。关键挑战在于:每个产品可能具备多个同类属性(例如 data-color="red white blue"),而用户可跨类别多选(如勾选“red”+“medium”+“solar”),系统应仅显示完全匹配全部已选条件的产品——即“交集过滤”,而非“任一匹配”。
以下是一个健壮、可扩展的纯前端实现方案:
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
✅ 核心逻辑说明
- 每个 .productItem 元素的 data-* 属性值为空格分隔的字符串(如 data-color="red white blue");
- 所有同类型复选框(如 data-filter-type="color")构成一个筛选组;
- 过滤规则是:只有当某产品在每个激活的筛选组中,都至少包含一个当前被勾选的值时,该产品才保留可见;
- 即:对每个已勾选的 checkbox,检查对应 productItem 的 data-[type] 属性是否包含其 value;所有检查均通过,才显示该产品。
✅ 完整可运行代码示例
<!-- 复选框结构(保持原样) -->
<h4 class="heading-primary">color</h4>
<ul>
<label><input type="checkbox" data-filter-type="color" value="red" /> red</label><br>
<label><input type="checkbox" data-filter-type="color" value="white" /> white</label><br>
<!-- ...其他选项 -->
</ul>
<!-- 产品列表(保持原样) -->
<div class="products">
<div class="productItem" data-color="red white blue" data-size="small medium" data-power="battery">Module 178</div>
<div class="productItem" data-color="orange" data-size="medium" data-power="battery solar">Module 231</div>
<!-- ...更多产品 -->
</div>
<script>
// 初始化:缓存所有产品元素和筛选组
const products = document.querySelectorAll('.productItem');
const filterGroups = {};
// 按 data-filter-type 分组收集所有复选框
document.querySelectorAll('input[type="checkbox"][data-filter-type]').forEach(checkbox => {
const type = checkbox.dataset.filterType;
if (!filterGroups[type]) filterGroups[type] = [];
filterGroups[type].push(checkbox);
});
// 主过滤函数
function applyFilters() {
products.forEach(product => {
let show = true;
// 遍历每个筛选组(如 color, size, power...)
for (const [type, checkboxes] of Object.entries(filterGroups)) {
// 获取该组中所有已勾选的值
const selectedValues = checkboxes
.filter(cb => cb.checked)
.map(cb => cb.value);
// 若该组无勾选,则跳过此组(不限制)
if (selectedValues.length === 0) continue;
// 获取当前 product 对应的 data 属性值(转为 Set 提升查找效率)
const attrValue = product.dataset[type];
const productValues = attrValue ? new Set(attrValue.split(/s+/)) : new Set();
// 检查:是否至少有一个已选值存在于 product 的属性中?
const hasMatch = selectedValues.some(val => productValues.has(val));
if (!hasMatch) {
show = false;
break; // 不满足任一条件,立即排除
}
}
product.style.display = show ? 'block' : 'none';
});
}
// 绑定事件监听(支持动态增删 checkbox)
document.addEventListener('change', e => {
if (e.target.type === 'checkbox' && e.target.hasAttribute('data-filter-type')) {
applyFilters();
}
});
// 页面加载后执行一次(确保初始状态正确)
applyFilters();
</script>⚠️ 注意事项与优化建议
- 性能友好:使用 Set 存储 data-* 值,O(1) 查找;避免重复 DOM 查询;
- 空格安全:正则 /\s+/ 可处理多个连续空格或制表符;
- 大小写敏感:默认区分大小写(如 "Temperature" ≠ "temperature"),如需忽略,统一转为 .toLowerCase() 处理;
- 空属性容错:若某 product 缺失某个 data-* 属性(如无 data-sensor),则 product.dataset.sensor 为 undefined,自动视为不匹配;
- 服务端回退:本方案完全客户端执行,适合中小型数据集(<500 产品);若产品量极大或需 SEO 支持,建议服务端渲染首屏 + 前端增强;
- 无障碍增强:可为 .products 添加 aria-live="polite",配合 aria-hidden 动态更新,提升屏幕阅读器体验。
该方案无需依赖 jQuery 或框架,兼容现代浏览器(IE11+ 需补全 Set),结构清晰、易于维护,并可轻松扩展新筛选维度(只需新增 data-filter-type 复选框及对应 data-* 属性即可)。

















