
本文介绍如何使用纯前端 javascript 实现多维度、多值 data 属性驱动的产品列表筛选,支持颜色、尺寸、电源类型等多组复选框联动过滤,且每个产品可同时匹配多个属性值(如 data-color="red white blue")。
本文介绍如何使用纯前端 javascript 实现多维度、多值 data 属性驱动的产品列表筛选,支持颜色、尺寸、电源类型等多组复选框联动过滤,且每个产品可同时匹配多个属性值(如 data-color="red white blue")。
在构建产品对比页时,常需让用户通过多组复选框(如颜色、尺寸、供电方式、传感器类型等)自由组合筛选条件。关键挑战在于:每个产品元素的 data 属性可能包含多个空格分隔的值(例如
以下是一个健壮、可扩展的纯前端解决方案:
✅ 核心逻辑说明
- 每个复选框通过 data-filter-type 标识所属维度(如 "color"、"size");
- 所有已勾选的值按维度归类,形成一个映射对象,例如:
{ color: ["red", "blue"], size: ["medium"], power: ["battery", "solar"] } - 遍历每个 .productItem 元素,对其每个 data-* 属性(如 data-color)执行校验:
- 将属性值按空格拆分为数组(el.dataset.color?.split(' ') || []);
- 检查当前维度下所有已选值是否都存在于该产品对应属性值数组中;
- 若任一维度存在未匹配项,则隐藏该产品;全部维度均满足才保留显示。
✅ 完整可运行代码示例
<script>
function initProductFilter() {
const products = document.querySelectorAll('.productItem');
const checkboxes = document.querySelectorAll('input[type="checkbox"][data-filter-type]');
// 按 filter-type 分组收集已选值
function getActiveFilters() {
const filters = {};
checkboxes.forEach(cb => {
if (!cb.checked) return;
const type = cb.dataset.filterType;
if (!filters[type]) filters[type] = [];
filters[type].push(cb.value);
});
return filters;
}
// 判断单个 product 是否匹配所有当前筛选条件
function matchesFilters(product, filters) {
for (const [type, values] of Object.entries(filters)) {
const attrName = `data-${type}`;
const productValues = (product.dataset[type] || '').split(' ').filter(v => v);
// 当前维度有选中值,但 product 不含其中任意一个 → 不匹配
if (values.length > 0 && !values.every(v => productValues.includes(v))) {
return false;
}
}
return true;
}
// 应用筛选
function applyFilter() {
const activeFilters = getActiveFilters();
products.forEach(p => {
p.style.display = matchesFilters(p, activeFilters) ? 'block' : 'none';
});
}
// 绑定事件(支持实时响应)
checkboxes.forEach(cb => cb.addEventListener('change', applyFilter));
// 初始化:首次加载时显示全部
products.forEach(p => p.style.display = 'block');
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', initProductFilter);
</script>
⚠️ 注意事项与优化建议
- 大小写敏感性:示例中 value="Temperature" 与 data-sensor="temperature" 不匹配。建议统一转为小写处理(在 getActiveFilters() 和 matchesFilters() 中对 cb.value 和 productValues 均调用 .toLowerCase())。
- 空格/多余空白处理:使用 .split(' ').filter(v => v.trim()) 更健壮地解析 data 属性。
- 性能优化:若产品数量超百,可考虑节流 change 事件,或使用 DocumentFragment 批量更新 DOM。
-
无障碍与 UX:为筛选区域添加 aria-live="polite",并在无结果时显示提示文案(如 暂无匹配产品)。
- 扩展性:如需支持“或关系”(如颜色选 red 或 blue),可增加 data-filter-mode="or" 属性并修改匹配逻辑。
该方案完全客户端执行,无需服务端参与,轻量、灵活、语义清晰,适用于中小型产品库的实时交互筛选场景。










