You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 07:53:12