核心是用 data-tab 与 data-tab-panel 属性值精确映射按钮和面板,避免 id 冲突或 dom 顺序依赖;切换时统一操作 hidden 属性、aria 状态及焦点管理,确保可复用、可访问、多实例共存。

用 data-tab 做选项卡切换,核心是靠属性值建立按钮和面板的映射关系,而不是硬写 ID 或依赖 DOM 顺序。这种方式可复用、易维护,且天然支持多组 tab 共存。
怎么用 data-tab 和 data-tab-pane 绑定面板
按钮和面板之间必须有明确、可查的关联。推荐用 data-tab(按钮)配 data-tab-pane(面板),而不是靠 id + href 或索引匹配。
- 每个按钮加
data-tab="json"、data-tab="xml"这类语义化值 - 对应面板加
data-tab-pane="json",并默认隐藏(比如加hidden属性或class="inactive") - JS 里用
document.querySelector('[data-tab-pane="json"]')精准定位,不依赖页面结构是否嵌套或重排 - 避免用
data-tab-id="1"这种数字索引——DOM 顺序一变就断链
点击时如何安全切换激活状态
切换本质是「移除所有旧状态,添加新状态」,但直接操作 style.display 或反复增删 class 容易漏掉边界情况。
- 统一用
hidden属性控制显隐:激活时el.removeAttribute('hidden'),非激活时el.hidden = true - CSS 中定义
[hidden] { display: none; },比写display: none !important更干净,也兼容 transition - 按钮上用
aria-selected="true"同步更新,屏幕阅读器才能感知当前 tab - 别只在按钮上绑
click,键盘用户按 Enter/Space 也需要触发,建议用addEventListener('click', ...)并在keydown里手动 dispatchclick
为什么不能只靠 querySelector 就完事
看似一行 document.querySelector(`[data-tab-pane="${tabValue}"]`) 就能拿到面板,但实际运行中容易出错。
- 如果用户手误写了
data-tab="jason"而面板是data-tab-pane="json",JS 不报错但找不到元素,面板永远不显示 - 多个 tab 区域共存时,
querySelector默认全局查找,可能跨区域误匹配——应限定在父容器内:container.querySelector(...) - 面板内容含
<pre class="brush:php;toolbar:false;"></pre>或动态渲染代码时,hidden比display: none更安全:它不会干扰子元素的position: absolute计算或导致滚动条闪动
键盘导航怎么补上 ArrowLeft/ArrowRight 支持
仅鼠标点开 tab 是不够的。键盘用户 Tab 进入后,左右键切 tab、Enter 激活,是 WCAG 强制要求。
- 所有 tab 按钮设
tabindex="0",非激活态按钮可设tabindex="-1"防止被跳到 - 监听
keydown,对ArrowLeft/ArrowRight找到兄弟按钮并调用.focus();对Enter/Space触发.click() - 激活后,焦点要自动移到对应
tabpanel(带role="tabpanel"的面板),并确保它有aria-labelledby指回按钮的id - 别忘了
Home/End键跳首尾——这两个常被忽略,但对长 tab 列表很关键
最易被忽略的是:每次切换都得同步更新 aria-selected、hidden、tabindex 三者,缺一不可。少设一个,对键盘或读屏用户就是功能断裂。这不是“锦上添花”,而是让 tab 真正可用的底线。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











