如何实现带垂直标签、点击垂直展开内容的React侧边栏菜单
React 垂直标签侧边栏菜单实现方案
核心实现思路
- 定义两个状态变量:
activeTab存储当前激活的标签ID,isExpanded标记侧边栏是否处于展开状态 - 收拢状态下仅展示60px宽度的垂直标签栏,用CSS实现文字垂直排列
- 点击标签时做判断:如果点击的是当前已激活标签则收起侧边栏,点击其他标签则切换激活项并保持展开状态
- 切换标签时内容区直接更新对应内容,不需要重复触发收起展开动画
完整代码示例
组件逻辑代码
import { useState } from 'react' import './VerticalSidebar.css' // 菜单配置,可根据需求自行扩展 const menuItems = [ { id: 'dashboard', label: '首页', icon: '🏠', content: [<p>数据概览</p>, <p>今日统计</p>, <p>待办事项</p>] }, { id: 'user', label: '用户管理', icon: '👤', content: [<p>用户列表</p>, <p>权限配置</p>, <p>用户分组</p>] }, { id: 'order', label: '订单管理', icon: '📦', content: [<p>全部订单</p>, <p>待发货订单</p>, <p>退款申请</p>] }, { id: 'setting', label: '系统设置', icon: '⚙️', content: [<p>基础配置</p>, <p>日志查看</p>, <p>版本更新</p>] } ] export default function VerticalSidebar() { const [activeTab, setActiveTab] = useState(null) const [isExpanded, setIsExpanded] = useState(false) // 标签点击事件 const handleTabClick = (tabId) => { if (activeTab === tabId) { // 点击当前激活标签则收起侧边栏 setIsExpanded(false) setActiveTab(null) } else { setActiveTab(tabId) setIsExpanded(true) } } return ( <div className="sidebar-container"> {/* 垂直标签栏 */} <div className="tab-bar"> {menuItems.map(item => ( <div key={item.id} className={`tab-item ${activeTab === item.id ? 'active' : ''}`} onClick={() => handleTabClick(item.id)} > <span className="tab-icon">{item.icon}</span> <span className="tab-label">{item.label}</span> </div> ))} </div> {/* 展开内容区 */} {isExpanded && activeTab && ( <div className="content-area"> <h4>{menuItems.find(i => i.id === activeTab).label}</h4> <div className="content-body"> {menuItems.find(i => i.id === activeTab).content} </div> </div> )} </div> ) }
配套样式代码(VerticalSidebar.css)
* { margin: 0; padding: 0; box-sizing: border-box; } .sidebar-container { display: flex; height: 100vh; position: fixed; left: 0; top: 0; z-index: 999; } /* 垂直标签栏样式 */ .tab-bar { width: 60px; background: #2d3436; display: flex; flex-direction: column; } .tab-item { padding: 24px 0; color: #fff; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 6px; transition: background 0.2s ease; } .tab-item:hover, .tab-item.active { background: #636e72; } .tab-icon { font-size: 20px; } .tab-label { /* 实现文字垂直排列 */ writing-mode: vertical-rl; text-orientation: mixed; font-size: 12px; } /* 展开内容区样式 */ .content-area { width: 240px; background: #fff; border-right: 1px solid #eee; padding: 16px; animation: slideIn 0.3s ease forwards; } @keyframes slideIn { from { transform: translateX(-10%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .content-body { margin-top: 16px; display: flex; flex-direction: column; gap: 16px; }
功能说明
- 初始状态侧边栏仅展示60px宽的垂直标签栏,符合收拢状态需求
- 点击任意标签后右侧弹出内容区,展示对应标签的子内容
- 点击当前已激活的标签时,内容区收起,回到仅展示标签的状态
- 切换不同标签时,内容区直接更新为对应标签的内容,无多余交互
- 所有样式均可根据实际设计需求调整宽度、颜色、动画效果等参数
内容的提问来源于stack exchange,提问作者Diana Sk
相关产品推荐
相关产品推荐

