基于多复选框值筛选多属性产品的前端实现疑问
多值Data属性的产品筛选实现(纯前端)
我想用JavaScript做一个产品对比页面,页面有多组复选框,用户选颜色、尺寸、供电方式这些条件后,只显示符合条件的产品。产品元素的data属性是多值的(比如data-color="red white blue"),之前找到过单值属性的筛选示例,但多值的搞不定,想问这个功能是不是必须后端来做?
示例HTML代码
<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> <label><input type="checkbox" data-filter-type="color" value="blue" /> blue</label><br> <label><input type="checkbox" data-filter-type="color" value="orange" /> orange</label><br> <label><input type="checkbox" data-filter-type="color" value="green" /> green</label><br/> <label><input type="checkbox" data-filter-type="color" value="purple" /> purple</label><br/> </ul> <h4 class="heading-primary">size</h4> <ul> <label><input type="checkbox" data-filter-type="size" value="small" /> small</label><br> <label><input type="checkbox" data-filter-type="size" value="medium" /> medium</label><br> <label><input type="checkbox" data-filter-type="size" value="large" /> large</label><br/> <label><input type="checkbox" data-filter-type="size" value="xl" />xl</label><br/> </ul> <h4 class="heading-primary">External power</h4> <ul> <label><input type="checkbox" data-filter-type="power" value="battery" /> Battery</label><br> <label><input type="checkbox" data-filter-type="power" value="solar" /> Solar</label><br> <label><input type="checkbox" data-filter-type="power" value="inductive" /> Inductive</label><br> </ul> <h4 class="heading-primary">casing </h4> <ul> <label><input type="checkbox" data-filter-type="casing" value="car" /> Car </label><br> <label><input type="checkbox" data-filter-type="casing" value="key" /> Key fob</label><br> <label><input type="checkbox" data-filter-type="casing" value="oem" /> Oem</label><br> </ul> <h4 class="heading-primary">Sensors</h4> <ul> <label><input type="checkbox" data-filter-type="sensor" value="acceleration" /> Acceleration</label><br> <label><input type="checkbox" data-filter-type="sensor" value="Temperature" /> Temperature</label><br> <label><input type="checkbox" data-filter-type="sensor" value="Humidity" /> Humidity</label><br> <label><input type="checkbox" data-filter-type="sensor" value="airquality" /> Air quality</label><br> <label><input type="checkbox" data-filter-type="sensor" value="magneto" /> Compass / Magneto</label><br> <label><input type="checkbox" data-filter-type="sensor" value="audio" /> Audio</label><br> <label><input type="checkbox" data-filter-type="sensor" value="barometer" /> Barometer / Altitude</label><br> <label><input type="checkbox" data-filter-type="sensor" value="distance" /> Distance</label><br> <label><input type="checkbox" data-filter-type="sensor" value="pir" /> Movement (PIR)</label><br> <label><input type="checkbox" data-filter-type="sensor" value="co2" /> Co2</label><br> <label><input type="checkbox" data-filter-type="sensor" value="light" /> Light sensor</label><br> </ul> <h4 class="heading-primary">External connectors</h4> <ul> <label><input type="checkbox" data-filter-type="extconnector" value="yes" /> Yes</label><br> <label><input type="checkbox" data-filter-type="extconnector" value="no" /> No</label><br> </ul> <div class="products"> <div class="productItem" data-color="red white blue orange purple green" data-size="small medium large" data-power="battery" data-extconnector="yes">Module 178<br></div> <div class="productItem" data-color="white" data-size="small medium large" data-power="inductive battery" data-extconnector="yes">Module R9B3<br></div> <div class="productItem" data-color="white" data-size="small medium large" data-power="powerC" data-extconnector="yes">Module 186<br></div> <div class="productItem" data-color="orange" data-size="small medium large" data-power="inductive battery" data-extconnector="no">Module 187/R9A11<br></div> <div class="productItem" data-color="orange" data-size="small medium large" data-power="inductive battery" data-extconnector="no">Module 3001<br></div> <div class="productItem" data-color="orange" data-size="medium" data-power="inductive battery solar" data-extconnector="no">Module 231<br></div> <div class="productItem" data-color="purple" data-size="medium" data-power="inductive battery" data-extconnector="no"> Module medium </div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 2001</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 2011</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 2016</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 2206</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 2207</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 2208</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no"> Module 1025</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no">Module 206</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no">Module 3101</div> <div class="productItem" data-color="purple" data-size="medium" data-power="battery" data-extconnector="no">Module power</div> </div>
纯前端实现方案
完全不用后端,纯JS就能搞定。核心思路是:收集用户选中的所有筛选条件,按类型分组,然后逐个检查产品是否满足所有选中的分组条件。
具体代码实现
// 获取所有复选框和产品元素 const checkboxes = document.querySelectorAll('input[type="checkbox"]'); const products = document.querySelectorAll('.productItem'); // 给每个复选框绑定筛选事件 checkboxes.forEach(checkbox => { checkbox.addEventListener('change', filterProducts); }); function filterProducts() { // 1. 收集选中的筛选条件,按类型分组 const filters = {}; checkboxes.forEach(checkbox => { if (checkbox.checked) { const type = checkbox.dataset.filterType; if (!filters[type]) { filters[type] = []; } filters[type].push(checkbox.value.toLowerCase()); // 转小写避免大小写问题 } }); // 2. 遍历每个产品,检查是否符合条件 products.forEach(product => { let isMatch = true; // 遍历每个筛选分组 for (const [type, values] of Object.entries(filters)) { // 获取产品对应的多值属性,转成小写数组 const productValues = product.dataset[type]?.toLowerCase().split(' ') || []; // 检查产品是否有至少一个值在当前筛选分组的选中值里 const hasMatch = values.some(value => productValues.includes(value)); if (!hasMatch) { isMatch = false; break; // 只要一个分组不满足,直接跳出 } } // 3. 根据匹配结果显示/隐藏产品 product.style.display = isMatch ? 'block' : 'none'; }); }
关键说明
- 分组收集筛选条件:把同一类型(比如color)的选中值放到一个数组里,方便后续检查。
- 多值属性处理:用
split(' ')把产品的多值data属性拆成数组,转小写是为了避免大小写匹配问题(比如筛选值是"red",产品属性是"Red")。 - 条件匹配逻辑:
- 如果某个筛选类型没有选中任何选项,就跳过该类型的检查(相当于不对该类型做限制)。
- 对于有选中项的类型,产品必须至少包含一个选中值才算符合该类型的条件。
- 只有所有有选中项的类型都符合,产品才会显示。
额外优化建议
- 给产品初始添加
display: block样式,确保默认显示所有产品。 - 如果要支持“全选/全不选”功能,可以给每个筛选组加按钮,批量控制复选框状态。
- 产品数量特别多时,用Debounce函数避免用户快速点击复选框时频繁触发筛选。
内容的提问来源于stack exchange,提问作者dennis
相关产品推荐
相关产品推荐

