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

Ant Design响应式导航栏中子菜单分组方法(解决div分组导致布局垂直错位问题)

如何在Ant Design水平导航栏中正确分组子菜单?

嘿,我来帮你搞定这个Ant Design导航栏的问题~你遇到的布局变垂直的问题,核心原因是Ant Design的Menu组件(尤其是mode="horizontal"模式下)只允许它的直接子节点是官方提供的Menu.Item、Menu.SubMenu、Menu.ItemGroup这类组件。如果你用<div>或者空片段<>来包裹一组子菜单,Menu无法识别这些自定义容器,就会破坏原本的水平布局逻辑,导致菜单项变成垂直排列。

下面给你几个针对性的解决方案,根据你的需求选择:

1. 逻辑分组(用于断点控制显示/隐藏)

如果你只是想把这些子菜单逻辑上归为一组,方便后续基于屏幕断点控制显示或隐藏,不需要额外的容器,直接用React的条件渲染结合Ant Design的useBreakpoint钩子就能实现:

import { Menu, useBreakpoint } from 'antd';
import { ShoppingCartOutlined, UserOutlined, DownOutlined } from '@ant-design/icons';
import { useState } from 'react';

const Navbar = () => {
  const { md } = useBreakpoint(); // md是断点阈值,小于md尺寸时会隐藏分组项
  const [menu, setMenu] = useState(null); // 你的Dropdown菜单逻辑
  const navbarClasses = []; // 你的自定义类名
  const logo = ''; // 你的logo地址
  const ukLogo = ''; // 你的语言图标地址

  return (
    <Menu 
      className={navbarClasses.join(" ")} 
      mode="horizontal" 
      style={{ padding: "5px", fontSize: "15px" }}
    >
      <Menu.Item className="logo_bottom">
        <img alt="logo" src={logo} className="logo" />
      </Menu.Item>

      {/* 基于断点控制这一组菜单项的显示 */}
      {md && (
        <>
          <Menu.SubMenu title="Demos" style={{ marginTop: "14px" }}>
            <Menu.Item>
              <a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">Modern</a>
            </Menu.Item>
            <Menu.Item>Classic</Menu.Item>
            <Menu.Item>Vintage</Menu.Item>
            <Menu.Item>Standard</Menu.Item>
            <Menu.Item>Minimal</Menu.Item>
            <Menu.Item>Trendy</Menu.Item>
            <Menu.Item>Elegant</Menu.Item>
          </Menu.SubMenu>
          <Menu.SubMenu key="smenu" title="Categories" style={{ marginTop: "14px" }}>
            <Menu.Item className="ant-dropdown-link">Fresh Vegetables</Menu.Item>
            <Menu.Item>Diet Nutrition</Menu.Item>
            <Menu.Item>Healthy Foods</Menu.Item>
            <Menu.Item>Grocery Items</Menu.Item>
            <Menu.Item>Beaf Steak</Menu.Item>
          </Menu.SubMenu>
          <Menu.SubMenu key="ssmenu" title="Dietary" style={{ marginTop: "14px" }}>
            <Menu.Item className="ant-dropdown-link">Vegetarian</Menu.Item>
            <Menu.Item>Kakogenic</Menu.Item>
            <Menu.Item>Mediterranean</Menu.Item>
            <Menu.Item>Organic</Menu.Item>
          </Menu.SubMenu>
          <Menu.Item style={{ marginTop: "14px" }}>Search</Menu.Item>
          <Menu.SubMenu title="Pages" style={{ marginRight: "auto", marginTop: "14px" }}>
            <Menu.SubMenu title="Users">
              <Menu.Item>My Account</Menu.Item>
              <Menu.Item>Sign In</Menu.Item>
              <Menu.Item>Sign Up</Menu.Item>
            </Menu.SubMenu>
            <Menu.Item>FAQ About Us</Menu.Item>
            <Menu.Item>Privacy Policy</Menu.Item>
            <Menu.Item>Terms & Condition</Menu.Item>
            <Menu.Item>Contact Us</Menu.Item>
            <Menu.Item>Checkout</Menu.Item>
            <Menu.Item>404</Menu.Item>
          </Menu.SubMenu>
        </>
      )}

      {/* 右侧始终显示的菜单项 */}
      <Menu.Item style={{ marginTop: "14px" }}>
        <Menu.Dropdown overlay={menu} trigger={["click"]}>
          <a className="ant-dropdown-link" onClick={(e) => e.preventDefault()}>
            <img alt="uk" src={ukLogo} className="lan-images" />
            English - EN
            <DownOutlined />
          </a>
        </Menu.Dropdown>
      </Menu.Item>
      <Menu.Item style={{ marginTop: "14px" }}>
        <button icon={<ShoppingCartOutlined style={{ fontSize: "20px" }} />} type="text" size="large">
          Cart
        </button>
      </Menu.Item>
      <Menu.Item style={{ marginTop: "14px" }}>
        <button icon={<UserOutlined style={{ fontSize: "20px" }} />} type="text" shape="round">
          Sign In
        </button>
      </Menu.Item>
    </Menu>
  );
};

2. 视觉分组(添加分隔线)

如果需要在视觉上区分不同组的菜单项,可以使用Ant Design内置的Menu.Divider组件(垂直分隔线),不需要自定义容器:

<Menu mode="horizontal">
  {/* 第一组菜单项 */}
  <Menu.SubMenu title="Demos">...</Menu.SubMenu>
  <Menu.SubMenu title="Categories">...</Menu.SubMenu>
  <Menu.SubMenu title="Dietary">...</Menu.SubMenu>
  
  {/* 垂直分隔线,视觉上分组 */}
  <Menu.Divider type="vertical" />
  
  {/* 第二组菜单项 */}
  <Menu.Item>Search</Menu.Item>
  <Menu.SubMenu title="Pages">...</Menu.SubMenu>
</Menu>

3. 小屏幕适配(转为汉堡菜单)

如果你的需求是在小屏幕上隐藏这组子菜单,改用汉堡菜单触发显示,那可以结合Drawer组件实现响应式适配:

import { Menu, useBreakpoint, Drawer, Button, Dropdown } from 'antd';
import { MenuOutlined, ShoppingCartOutlined, UserOutlined, DownOutlined } from '@ant-design/icons';
import { useState } from 'react';

const Navbar = () => {
  const { md } = useBreakpoint();
  const [drawerVisible, setDrawerVisible] = useState(false);
  const [menu, setMenu] = useState(null);
  const navbarClasses = [];
  const logo = '';
  const ukLogo = '';

  // 抽屉内的菜单内容
  const drawerMenu = (
    <Menu mode="vertical">
      <Menu.SubMenu title="Demos">
        <Menu.Item>Modern</Menu.Item>
        <Menu.Item>Classic</Menu.Item>
        <Menu.Item>Vintage</Menu.Item>
      </Menu.SubMenu>
      <Menu.SubMenu title="Categories">
        <Menu.Item>Fresh Vegetables</Menu.Item>
        <Menu.Item>Diet Nutrition</Menu.Item>
      </Menu.SubMenu>
      <Menu.SubMenu title="Dietary">
        <Menu.Item>Vegetarian</Menu.Item>
        <Menu.Item>Mediterranean</Menu.Item>
      </Menu.SubMenu>
      <Menu.Item>Search</Menu.Item>
      <Menu.SubMenu title="Pages">
        <Menu.SubMenu title="Users">
          <Menu.Item>My Account</Menu.Item>
          <Menu.Item>Sign In</Menu.Item>
        </Menu.SubMenu>
      </Menu.SubMenu>
    </Menu>
  );

  return (
    <>
      <Menu 
        className={navbarClasses.join(" ")} 
        mode="horizontal" 
        style={{ padding: "5px", fontSize: "15px" }}
      >
        <Menu.Item className="logo_bottom">
          <img alt="logo" src={logo} className="logo" />
        </Menu.Item>

        {/* 大屏幕显示完整菜单项 */}
        {md && (
          <>
            <Menu.SubMenu title="Demos" style={{ marginTop: "14px" }}>
              {/* 子项内容 */}
            </Menu.SubMenu>
            <Menu.SubMenu key="smenu" title="Categories" style={{ marginTop: "14px" }}>
              {/* 子项内容 */}
            </Menu.SubMenu>
            {/* 其他子菜单... */}
          </>
        )}

        {/* 小屏幕显示汉堡按钮 */}
        {!md && (
          <Menu.Item>
            <Button icon={<MenuOutlined />} onClick={() => setDrawerVisible(true)} />
          </Menu.Item>
        )}

        {/* 右侧固定菜单项 */}
        <Menu.Item style={{ marginTop: "14px" }}>
          <Dropdown overlay={menu} trigger={["click"]}>
            <a className="ant-dropdown-link" onClick={(e) => e.preventDefault()}>
              <img alt="uk" src={ukLogo} className="lan-images" />
              English - EN
              <DownOutlined />
            </a>
          </Dropdown>
        </Menu.Item>
        <Menu.Item style={{ marginTop: "14px" }}>
          <Button icon={<ShoppingCartOutlined style={{ fontSize: "20px" }} />} type="text" size="large">
            Cart
          </Button>
        </Menu.Item>
        <Menu.Item style={{ marginTop: "14px" }}>
          <Button icon={<UserOutlined style={{ fontSize: "20px" }} />} type="text" shape="round">
            Sign In
          </Button>
        </Menu.Item>
      </Menu>

      {/* 小屏幕抽屉菜单 */}
      <Drawer
        title="Navigation Menu"
        placement="left"
        onClose={() => setDrawerVisible(false)}
        open={drawerVisible}
        width={280}
      >
        {drawerMenu}
      </Drawer>
    </>
  );
};

核心要点就是:Ant Design的水平Menu不支持自定义容器作为直接子节点,必须使用官方提供的Menu系列组件,分组逻辑可以通过响应式钩子、内置分隔线或者小屏幕适配组件来实现。

内容的提问来源于stack exchange,提问作者Anwar Hossain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 20:52:44