data-category是唯一推荐的筛选绑定方式,须全小写短横线命名、值无空格,多选用Set管理,显隐通过.hidden类控制,同步URL hash、aria-pressed及“全部”按钮逻辑确保状态闭环。

data-category 是唯一推荐的筛选绑定方式
别用 class 模拟标签分类,比如 class="tag-react tag-node" —— 它会导致匹配不精确(tag-reactive 也会被选中)、样式类膨胀、且无法区分“分类”和“状态”语义。所有筛选项和目标内容必须统一用 data-category(或你自定义的 data-* 键)存小写无空格值:
<button data-category="react">React</button><article data-category="react">...</article>
命名必须全小写、短横线分隔(data-user-id ✅,data-userId ❌),否则 dataset 读不到;值里带空格或引号?直接用 getAttribute('data-category') 更稳妥。
多选标签必须用 Set 管理已选项
用户按住 Ctrl 或连续点击多个标签时,硬编码 if (cat === 'react' || cat === 'vue') 会迅速失控。正确做法是维护一个动态 Set:
- 点击时:
selectedCategories.add(event.target.dataset.category) - 取消时:
selectedCategories.delete(...) - 过滤逻辑:
Array.from(articles).filter(el => selectedCategories.has(el.dataset.category))
用 Set 而不是数组,是因为 .has() 是 O(1) 查找,100 个标签时性能差距明显;也避免重复添加同一标签导致逻辑错乱。
显隐控制必须走 CSS 类,不能碰 style.display
直接写 el.style.display = 'none' 会覆盖元素原始 display 值(比如 inline-flex 变成 block),重置时还得记原始值,极易出错。定义一个 .hidden 类:
.hidden {
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
}
然后统一用:el.classList.toggle('hidden', shouldHide)。这样不破坏文档流、支持过渡动画、移动端点击反馈自然,也不用担心 display 类型丢失。
按钮状态同步容易被忽略的三个点
筛选 UI 的“活”不在于过滤本身,而在于状态是否闭环。以下三点漏掉任一,用户就会觉得“点了没反应”:
- URL hash 同步:点击后执行
history.replaceState(null, '', `#category=${Array.from(selectedCategories).join(',')}`),页面加载时从location.hash解析并还原 - 按钮
aria-pressed更新:用btn.setAttribute('aria-pressed', selectedCategories.has(cat)),保障屏幕阅读器可感知 - “全部”按钮逻辑:不是重新渲染 DOM,而是遍历所有目标元素,批量
el.classList.remove('hidden'),保留原始结构和事件绑定
真正难的从来不是“怎么筛”,而是“筛完之后,所有地方都还对得上”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











