用data-category存分类标识最轻量可控:它专为元数据设计,避免class语义混乱和匹配歧义;筛选时用activecategories数组配合dataset.category判断显隐,通过classlist.toggle("hidden")控制,不直接操作style.display,并同步data-active、url hash及事件状态。

用 data-category 存分类标识,配合 querySelectorAll() + classList.toggle() 实现筛选,是最轻量、最可控的方式。别用 class 名做筛选依据,也别直接操作 style.display。
为什么必须用 data-category 而不是 class
很多人把分类塞进 class 里,比如 class="item category-laptop category-new",然后用 document.querySelectorAll(".category-laptop") 拿元素——这会误匹配 category-laptop-accessory,而且 class 名越堆越多,语义混乱。
-
data-category是专为存储自定义元数据设计的,浏览器保证只读、不参与样式,值唯一且可预测 - 写法必须全小写+短横线:
data-category="laptop"✅,data-categoryName="laptop"❌(IE11 及现代浏览器都会忽略) - JS 里读取统一用
element.dataset.category,不用getAttribute("data-category")——除非你明确需要原始字符串(比如含前导零或科学计数法)
筛选逻辑怎么写才支持多选和重置
单选时容易处理,但真实场景常要「笔记本 或 显示器 或 平板」一起显示。硬编码 if (cat === "laptop" || cat === "monitor") 不可维护,新增分类就得改 JS。
- 把当前激活的分类存在数组里:
const activeCategories = ["laptop", "monitor"] - 遍历每个内容项,用
activeCategories.includes(item.dataset.category)判断是否显示 - 重置筛选时,不要重建 DOM 或设
innerHTML,只需清除所有.hidden类:items.forEach(el => el.classList.remove("hidden")) - 如果某次筛选后没结果,记得显式插入一个
<p class="no-results">暂无匹配项目</p>,否则页面会“变空”
显隐控制为什么不能直接设 display: none
直接写 el.style.display = "none" 看似简单,但会覆盖元素原本的 display 值(比如 inline-block 变成 block),导致布局错位;动画也难衔接。
- 推荐用 CSS 类控制:
.item.hidden { opacity: 0; pointer-events: none; transition: opacity 0.2s; } - 切换用
el.classList.toggle("hidden", shouldHide),不干扰原有 display 流 - 如果真要隐藏结构(比如 SEO 要求),再加
visibility: hidden或aria-hidden="true",但多数情况opacity + pointer-events更稳妥
事件绑定和状态同步最容易被忽略的点
筛选器真正卡住用户的,往往不是 DOM 操作本身,而是状态没跟上:点了按钮没高亮、URL 不变、后退键失效、分页加载后筛选丢失。
- 点击标签时,先清掉所有
data-active属性,再给当前设data-active="true",避免多个标签同时 active - 用
history.replaceState()同步 URL hash,比如#category=laptop,monitor,页面加载时从 hash 初始化activeCategories - 如果内容是异步加载的(如分页),别依赖
document.querySelectorAll每次重查——缓存节点列表,或用事件委托监听父容器 - 阻止
<a href="#"></a>的默认跳转,否则页面会闪一下
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











