如何使用React.js与Material UI实现多列多行的巨型菜单(Mega menu)
嘿,我之前刚好实现过类似的巨型菜单需求,用Material UI完全可以搞定!其实核心思路是:Material UI的Menu组件只是提供了弹出的容器,内部的布局完全可以自己掌控,不用局限于它默认的列表结构,咱们用Grid或者Flex就能轻松实现多列多行的效果。
核心实现步骤
- 搭建基础Menu触发结构:先做一个触发菜单的按钮,用
anchorEl控制菜单的显示/隐藏逻辑,这部分和普通Menu的用法一致。 - 自定义内部多列布局:在Menu的内容区域,用Material UI的
Grid组件来划分列和行——把整个菜单容器设为Grid container,然后把每一组菜单项放到Grid item里,指定每列的宽度占比。 - 调整菜单样式适配需求:默认的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
相关产品推荐
相关产品推荐

