使用原生Vanilla JS结合HTML data属性实现产品筛选功能遇到问题求助
实现方案合理性说明
用HTML的data-*自定义属性实现产品分类筛选是这个场景下非常合适的实现方案,属于中小型项目的最优选择:不需要额外维护筛选条件和产品的映射关系,语义化清晰,代码易读易维护,后续新增分类只需要加对应按钮和给产品打对应data属性标记即可,不需要改逻辑代码。
现有代码问题&修正方案
你的代码逻辑思路是对的,只存在几个细节错误导致功能异常:
data-filter属性位置错误
你把data-filter属性加在了产品卡片内部的<img>标签上,但JS里筛选遍历的是带.products类的外层卡片div,所以永远拿不到匹配的筛选值,需要把所有data-filter属性从img标签迁移到对应的外层产品div上,img上的属性可以删除。- 未处理「全部展示」的逻辑
点击All按钮时,拿到的按钮文本转小写后是all,没有产品的data-filter是all,会导致所有产品被隐藏,需要新增对应判断分支。 - 按钮激活样式设置错误
button.className = 'active'会直接覆盖按钮原本的btn filter-btn类,导致按钮原有样式丢失,应该用classList.add('active')方法追加类名。 - 变量未声明
showProduct没有加变量声明,会变成隐式全局变量,容易触发不可预期的bug。
修正后代码
JS代码
const buttons = document.querySelectorAll('.btn') const products = document.querySelectorAll('.products') buttons.forEach(function (button) { button.addEventListener('click', (event) => { event.preventDefault() // 切换按钮激活状态 buttons.forEach((btn) => btn.classList.remove('active')) button.classList.add('active') const filterKey = button.textContent.toLowerCase() products.forEach(product => { // 处理全选逻辑,匹配则显示,否则隐藏 if (filterKey === 'all' || product.dataset.filter === filterKey) { product.style.display = 'block' } else { product.style.display = 'none' } }) }) })
HTML修改示例
只需要调整每个产品卡片的外层div属性即可,比如蛋糕类产品:
<!-- 把data-filter加在外层div上 --> <div class="w-72 products max-w-full border border-gray-300 rounded-sm bg-white" data-filter='cake'> <div class="w-full h-48"> <!-- 删掉img上的data-filter属性 --> <img src="https://images.pexels.com/photos/291528/pexels-photo-291528.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260" class="w-full h-full object-cover"/> </div> <!-- 其余内部结构不变 --> </div>
所有分类的产品卡片都按照上面的格式调整即可正常运行。
内容的提问来源于stack exchange,提问作者CrveniFlash
相关产品推荐
相关产品推荐

