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

如何使用React.js与Material UI实现多列多行的巨型菜单(Mega menu)

如何用React + Material UI实现多列多行的巨型菜单(Mega Menu)

嘿,我之前刚好实现过类似的巨型菜单需求,用Material UI完全可以搞定!其实核心思路是:Material UI的Menu组件只是提供了弹出的容器,内部的布局完全可以自己掌控,不用局限于它默认的列表结构,咱们用Grid或者Flex就能轻松实现多列多行的效果。

核心实现步骤

  1. 搭建基础Menu触发结构:先做一个触发菜单的按钮,用anchorEl控制菜单的显示/隐藏逻辑,这部分和普通Menu的用法一致。
  2. 自定义内部多列布局:在Menu的内容区域,用Material UI的Grid组件来划分列和行——把整个菜单容器设为Grid container,然后把每一组菜单项放到Grid item里,指定每列的宽度占比。
  3. 调整菜单样式适配需求:默认的Menu有内边距和固定宽度,我们可以通过sx属性自定义弹出层的宽度、内边距、阴影这些样式,让它更符合巨型菜单的视觉效果。

完整代码示例

import React from 'react';
import { Menu, MenuItem, Button, Grid, Typography } from '@mui/material';

export default function MegaMenu() {
  const [anchorEl, setAnchorEl] = React.useState(null);
  const open = Boolean(anchorEl);

  // 菜单显示/隐藏的控制函数
  const handleMenuOpen = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleMenuClose = () => {
    setAnchorEl(null);
  };

  // 模拟按列分组的菜单数据,你可以根据实际需求替换
  const megaMenuData = [
    {
      columnTitle: "产品系列",
      items: ["智能硬件", "软件服务", "解决方案", "定制产品"]
    },
    {
      columnTitle: "支持服务",
      items: ["技术文档", "在线客服", "售后维修", "培训课程"]
    },
    {
      columnTitle: "关于我们",
      items: ["公司介绍", "新闻动态", "招贤纳士", "联系我们"]
    }
  ];

  return (
    <div>
      {/* 菜单触发按钮 */}
      <Button
        id="mega-menu-trigger"
        aria-controls={open ? 'mega-menu-container' : undefined}
        aria-haspopup="true"
        aria-expanded={open ? 'true' : undefined}
        onClick={handleMenuOpen}
        variant="contained"
      >
        展开巨型菜单
      </Button>

      {/* 巨型菜单主体 */}
      <Menu
        id="mega-menu-container"
        anchorEl={anchorEl}
        open={open}
        onClose={handleMenuClose}
        // 自定义弹出层的样式
        sx={{
          '& .MuiMenu-paper': {
            width: '700px', // 设置菜单的总宽度
            padding: '2rem', // 内部内边距
            boxShadow: '0 6px 20px rgba(0, 0, 0, 0.12)', // 自定义阴影
            borderRadius: '8px'
          }
        }}
        // 禁用MenuList的默认内边距,避免布局错位
        MenuListProps={{
          disablePadding: true
        }}
      >
        {/* 多列布局容器 */}
        <Grid container spacing={4}>
          {megaMenuData.map((column, columnIndex) => (
            <Grid item xs={4} key={columnIndex}>
              {/* 列标题 */}
              <Typography variant="h6" fontWeight="bold" gutterBottom>
                {column.columnTitle}
              </Typography>
              {/* 列内的菜单项 */}
              {column.items.map((item, itemIndex) => (
                <MenuItem 
                  key={itemIndex} 
                  onClick={handleMenuClose}
                  sx={{ paddingY: '0.5rem' }} // 调整单个菜单项的上下内边距
                >
                  {item}
                </MenuItem>
              ))}
            </Grid>
          ))}
        </Grid>
      </Menu>
    </div>
  );
}

额外优化建议

  • 响应式适配:如果需要适配移动端,可以把Grid的xs={4}改成xs={6} md={4},这样在小屏幕上会自动变成2列布局。
  • 超长内容滚动:如果某一列的菜单项特别多,可以给Grid item加上maxHeight: '350px'和overflowY: 'auto',让这一列可以滚动,避免菜单过高。
  • 自定义 hover 效果:可以通过sx给MenuItem添加hover样式,比如改变背景色或者文字颜色,提升交互体验。

内容的提问来源于stack exchange,提问作者prashant bhat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:57:36