
本文介绍一种基于 data-filter 属性与 DOM 批量遍历的现代 JavaScript 方案,替代为每个元素手动增删 active/hidden 类的冗余写法,提升代码可维护性、扩展性与专业度。
本文介绍一种基于 `data-filter` 属性与 dom 批量遍历的现代 javascript 方案,替代为每个元素手动增删 `active`/`hidden` 类的冗余写法,提升代码可维护性、扩展性与专业度。
在食品分类筛选这类常见交互场景中,若对 8 个甚至更多食品项分别编写 classList.add('active') 和 classList.remove('hidden'),不仅代码臃肿、难以维护,更违背了 DRY(Don’t Repeat Yourself)原则。真正的“干净代码”不在于行数少,而在于抽象合理、职责清晰、易于扩展。
核心思路是:用语义化数据属性标记内容类型,用统一逻辑驱动状态切换。我们为按钮添加 data-filter="breakfast" 等标识,为食品容器添加 data-filter="breakfast,lunch"(支持多标签),再通过一次遍历完成全部显隐控制。
以下是精简、健壮的实现方案:
// 统一绑定所有筛选按钮事件
document.querySelectorAll('.filter-buttons button').forEach(button => {
button.addEventListener('click', function() {
// 1. 更新按钮激活态(视觉反馈)
document.querySelectorAll('.filter-buttons button').forEach(el => el.classList.remove('active'));
this.classList.add('active');
// 2. 获取当前筛选类型
const filterType = this.dataset.filter;
// 3. 批量处理所有食品项
document.querySelectorAll('.filter > div').forEach(item => {
if (filterType === 'all') {
item.classList.add('active');
} else {
// 支持多值匹配(如 data-filter="breakfast,lunch")
const itemFilters = item.dataset.filter.split(',').map(s => s.trim());
item.classList.toggle('active', itemFilters.includes(filterType));
}
});
});
});
配套 CSS 仅需两行即可实现显隐控制(无需 hidden 类):
.filter > div:not(.active) { display: none; }
.filter-buttons button.active { border-color: #e74c3c; }
HTML 结构简洁语义化:
<div class="filter-buttons"> <button class="active" data-filter="all">全部</button> <button data-filter="breakfast">早餐</button> <button data-filter="lunch">午餐</button> <button data-filter="drinks">饮品</button> </div> <div class="filter"> <div data-filter="breakfast">燕麦杯</div> <div data-filter="breakfast,lunch">三明治</div> <div data-filter="drinks">冰美式</div> <div data-filter="lunch">咖喱饭</div> <!-- 更多项... --> </div>
✅ 优势总结:
- ✅ 零硬编码:新增食品项无需修改 JS,只需补充 HTML 中的 data-filter;
- ✅ 天然支持多标签:一个食品可同时属于多个类别(如“三明治”既是早餐也是午餐);
- ✅ 状态解耦:显示逻辑完全由 active 类控制,CSS 负责表现,JS 专注行为;
- ✅ 可扩展性强:后续增加“晚餐”“甜点”等新分类,仅需新增按钮和对应 data-filter 值。
? 提示:若需过渡动画,可在 .filter > div 上添加 transition: opacity 0.2s,并用 opacity 替代 display 控制显隐(配合 visibility: hidden 防止布局抖动)。但对基础筛选功能而言,display: none 语义更准确、性能更优。










