
本文介绍一种纯 javascript 实现的标签式内容切换方案:页面加载时默认激活首个导航项并显示对应内容,点击其他导航按钮时自动高亮当前项、隐藏其他内容,无需 jquery,代码简洁可维护。
在构建单页应用或模块化内容区域(如产品介绍、客户案例、服务选项等)时,常需实现“点击导航按钮 → 切换下方内容”的交互效果。理想方案应满足:① 页面初始加载即正确激活第一个导航项并显示其内容;② 点击任意导航项时,仅该按钮高亮、对应内容显示,其余内容隐藏;③ 逻辑清晰、无冗余判断、兼容现代浏览器。
以下是一个轻量、可扩展的原生 JavaScript 实现:
✅ HTML 结构(语义清晰,便于维护)
<div class="tab-nav"> <button type="button" data-target="div1" class="tab-link active">div1</button> <button type="button" data-target="div2" class="tab-link">div2</button> </div> <div class="tab-content"> <section id="div1" class="tab-pane active"> <p>This is div 1.</p> </section> <section id="div2" class="tab-pane"> <p>Div2 is different from div1</p> </section> </div>
? 推荐使用 <button> 替代 <p onclick=”…”>:更语义化、天然支持键盘操作(无障碍友好),且避免内联事件绑定。
✅ CSS 样式(基于类控制显隐,解耦逻辑与表现)
.tab-nav { display: grid; grid-template-columns: 1fr 1fr; margin: 0 auto; gap: 1rem; } .tab-link { border: none; background: none; padding: 0.5rem 1rem; font-size: 1rem; cursor: pointer; border-bottom: 0.18rem solid transparent; transition: color 0.2s, border-color 0.2s; } .tab-link:hover:not(.active) { color: #970fc2; border-bottom-color: #970fc2; } .tab-link.active#div1-link, .tab-link[data-target="div1"].active { border-bottom-color: #970fc2; color: #970fc2; } .tab-link.active#div2-link, .tab-link[data-target="div2"].active { border-bottom-color: #52b54b; color: #52b54b; } .tab-pane { display: none; } .tab-pane.active { display: block; }
⚠️ 注意:不要依赖 element.style.display 判断可见性——它仅读取内联样式(style=”display:none”),而你的初始隐藏状态由 CSS 规则 #div2-content { display: none; } 控制,此时 div2Content.style.display 为空字符串,导致判断失效。正确方式是使用 getComputedStyle(element).display 获取最终计算值(见下文 js 逻辑)。
✅ JavaScript 逻辑(简洁、健壮、可复用)
// 获取所有导航按钮和内容区块 const tabLinks = document.querySelectorAll('.tab-link'); const tabPanes = document.querySelectorAll('.tab-pane'); // 初始化:确保首个 tab-link 和首个 tab-pane 处于 active 状态 if (tabLinks.length > 0 && tabPanes.length > 0) { tabLinks[0].classList.add('active'); tabPanes[0].classList.add('active'); } // 统一处理点击事件 tabLinks.forEach(link => { link.addEventListener('click', () => { const targetId = link.dataset.target; const targetPane = document.getElementById(targetId); // 防御性检查 if (!targetPane) return; // 移除所有 active 状态 tabLinks.forEach(l => l.classList.remove('active')); tabPanes.forEach(p => p.classList.remove('active')); // 激活当前项 link.classList.add('active'); targetPane.classList.add('active'); }); });
✅ 关键优势说明
- 零依赖:完全使用原生 dom API,适合 JavaScript 初学者理解事件流与 DOM 操作;
- 可扩展性强:只需新增 <button data-target=”xxx”> 和 <section id=”xxx”>,逻辑自动适配;
- 状态管理清晰:通过 active 类统一控制 ui 状态,CSS 负责视觉反馈,JS 专注行为逻辑;
- 健壮性保障:添加了 dataset.target 存在性校验,避免因 HTML 错误导致脚本中断;
- 无障碍友好:<button> 支持空格/回车触发,配合 aria-controls 可进一步增强(进阶建议)。
? 总结
避免直接读取 element.style.xxx 判断样式状态——它无法反映 CSS 规则生效后的最终效果。应优先使用 getComputedStyle() 或(更推荐)采用基于类名的状态驱动模式(如本例的 .active),让 CSS 承担表现职责,JavaScript 专注状态调度。这种分离思想是构建可维护前端交互的基础范式。