React侧边栏:子菜单父项高亮与独立滚动实现问题
问题解决方案
一、修复"Leave"项在子路由下的高亮问题
当前代码中,getItemFromPathname仅匹配路径最后一段,当跳转到/leave/apply这类子路由时,无法识别为"Leave"项。修改该函数,判断路径是否包含/leave即可:
const getItemFromPathname = (pathname) => { // 优先判断是否为Leave相关路由 if (pathname.startsWith("/leave")) { return "Leave"; } const parts = pathname.split("/"); const lastPart = parts[parts.length - 1]; switch (lastPart) { case "": case "profile": return "Profile"; case "calendar": return "Calendar"; default: return ""; } };
同时确保路由配置中,ApplyLeave组件的路径属于/leave的子路由或扩展路径:
<Routes> <Route path="/leave" element={<Leave />} /> <Route path="/leave/apply" element={<ApplyLeave />} /> {/* 其他路由配置 */} </Routes>
二、实现YouTube风格的固定滚动侧边栏
修改Sidebar.css添加以下样式,让侧边栏独立于页面滚动,仅在内容溢出时显示滚动条:
.sidebar { position: fixed; top: 0; left: 0; height: 100vh; /* 占满整个视口高度 */ width: 240px; /* 可根据需求调整宽度 */ overflow-y: auto; /* 内容超出时显示垂直滚动条 */ background-color: #ffffff; /* 背景色按需调整 */ border-right: 1px solid #e5e7eb; /* 右侧分隔线可选 */ padding: 16px 0; } /* 自定义滚动条样式,模拟YouTube效果 */ .sidebar::-webkit-scrollbar { width: 8px; } .sidebar::-webkit-scrollbar-track { background: transparent; } .sidebar::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, 0.2); border-radius: 4px; } .sidebar:hover::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, 0.4); } /* 主内容区域添加左侧边距,避免被侧边栏遮挡 */ .main-content { margin-left: 240px; /* 与侧边栏宽度保持一致 */ padding: 20px; }
页面布局结构需调整为:
<div className="app-layout"> <Sidebar /> <main className="main-content"> <Outlet /> {/* 路由出口,渲染匹配的页面组件 */} </main> </div>
三、冗余代码优化
移除Sidebar组件中手动设置selectedItem的逻辑,因为路由变化后useEffect会自动更新选中状态:
function Sidebar() { const location = useLocation(); const [selectedItem, setSelectedItem] = useState(""); useEffect(() => { const item = getItemFromPathname(location.pathname); setSelectedItem(item); }, [location]); const getItemFromPathname = (pathname) => { if (pathname.startsWith("/leave")) { return "Leave"; } const parts = pathname.split("/"); const lastPart = parts[parts.length - 1]; switch (lastPart) { case "": case "profile": return "Profile"; case "calendar": return "Calendar"; default: return ""; } }; return ( <section className="sidebar"> <SidebarItem to="/" title="Profile" selected={selectedItem === "Profile"} /> <SidebarItem to="/calendar" title="Calendar" selected={selectedItem === "Calendar"} /> <SidebarItem to="/leave" title="Leave" selected={selectedItem === "Leave"} /> </section> ); }
同时简化SidebarItem组件,移除不必要的onClick属性:
function SidebarItem(props) { return ( <Link to={props.to} className="sidebar-item-link"> <div className={`sidebar-item ${props.selected && "selected"}`} > {props.title} </div> </Link> ); }
内容的提问来源于stack exchange,提问作者Bishwaroop Dey
相关产品推荐
相关产品推荐

