React中使用MUI Grid组件布局如何避免元素重叠问题?
问题根因
- MUI 内置的
<AppBar>组件默认采用position: fixed定位,会脱离正常文档流,不会占用页面实际高度,因此下方的 Features 内容会从页面最顶部开始渲染,被悬浮的 AppBar 遮挡 - 原有布局结构逻辑错误:PageHeader 是顶部通栏导航组件,不应该放置在左侧 3 列宽度的 Grid 容器中,需要独立置于页面最顶部
- 侧边栏 Drawer 与主内容区均未预留与 AppBar 等高的顶部间距,导致多层组件重叠
完整修改方案
1. 修改 App.js,重构全局布局结构
import './App.css'; import { Grid, Box } from '@mui/material'; import SideMenu from './components/home/SideMenu'; import Features from './components/home/Features'; import PageHeader from './components/home/PageHeader'; // 统一管理侧边栏宽度,避免多文件重复定义 export const DRAWER_WIDTH = 240; function App() { return ( <Box sx={{ display: 'flex', width: '100%' }}> {/* 顶部通栏导航 */} <PageHeader /> {/* 侧边菜单 */} <SideMenu /> {/* 主内容区,预留顶部AppBar高度和左侧侧边栏宽度的边距 */} <Box component="main" sx={{ flexGrow: 1, p: 3, marginTop: '64px', // 对应MUI默认Toolbar的高度,可通过theme变量适配响应式尺寸 marginLeft: `${DRAWER_WIDTH}px`, }} > <Features /> </Box> </Box> ); } export default App;
2. 修改 PageHeader.js,调整AppBar适配逻辑
import * as React from 'react'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; import { Grid } from '@mui/material'; import { DRAWER_WIDTH } from '../../App'; // 导入统一的侧边栏宽度 const LOGGED_IN = false const getButtons = (isLogin) => { if (isLogin) { return <Grid container> <Grid item xs={7}></Grid> <Grid item xs={2} > <Button color="inherit"> <Typography variant="h6" component="div"> Profile </Typography> </Button> </Grid> <Grid item xs={2} > <Button color="inherit"> <Typography variant="h6" component="div"> Logout </Typography> </Button> </Grid> </Grid> } return <Grid container> <Grid item xs={9}></Grid> <Grid item xs={2}> <Button color="inherit"> <Typography variant="h6" component="div"> Login </Typography> </Button> </Grid> </Grid> } export default function PageHeader(props) { return ( <AppBar sx={{ width: { sm: `calc(100% - ${DRAWER_WIDTH}px)` }, ml: { sm: `${DRAWER_WIDTH}px` }, }} > <Toolbar> <Grid item xs={4}> <Typography variant="h3" component="div"> Stonks! </Typography> </Grid> {getButtons(LOGGED_IN)} </Toolbar> </AppBar> ); }
3. 修改 SideMenu.js,简化冗余布局代码
import * as React from 'react'; import { Divider, Drawer, List, ListItem, ListItemIcon, ListItemText } from '@mui/material'; import { styled } from '@mui/material/styles'; import BusinessIcon from '@mui/icons-material/Business'; import ShowChartIcon from '@mui/icons-material/ShowChart'; import AppsIcon from '@mui/icons-material/Apps'; import SupervisedUserCircleIcon from '@mui/icons-material/SupervisedUserCircle'; import InfoIcon from '@mui/icons-material/Info'; import CreateIcon from '@mui/icons-material/Create'; import { DRAWER_WIDTH } from '../../App'; // 导入统一的侧边栏宽度 // 该组件高度默认与Toolbar等高,用于侧边栏顶部预留AppBar的位置 const DrawerHeader = styled('div')(({ theme }) => ({ ...theme.mixins.toolbar, })) export default function SideMenu(props) { return ( <Drawer sx={{ width: DRAWER_WIDTH, flexShrink: 0, boxSizing: 'border-box', '& .MuiDrawer-paper': { width: DRAWER_WIDTH, boxSizing: 'border-box', }, }} variant="persistent" anchor="left" open={true} > <DrawerHeader /> <Divider /> <List> {['Companies', 'Exchanges', 'Sectors', 'Users'].map((text) => ( <ListItem button key={text}> <ListItemIcon> {(() => { switch (text) { case 'Companies': return <BusinessIcon /> case 'Exchanges': return <ShowChartIcon /> case 'Sectors': return <AppsIcon /> case 'Users': return <SupervisedUserCircleIcon /> } })()} </ListItemIcon> <ListItemText primary={text} /> </ListItem> ))} </List> <Divider /> <List> {['About', 'Creators'].map((text) => ( <ListItem button key={text}> <ListItemIcon> {(() => { switch (text) { case 'About': return <InfoIcon /> case 'Creators': return <CreateIcon /> } })()} </ListItemIcon> <ListItemText primary={text} /> </ListItem> ))} </List> </Drawer> ); }
Features.js、DisplayCard.js 无需修改即可正常使用,修改完成后所有组件不会再出现重叠问题。
内容的提问来源于stack exchange,提问作者Mohit Motiani
相关产品推荐
相关产品推荐

