Material-UI Drawer组件temporary变体桌面端不显示问题
解决Material-UI Drawer响应式显示问题(移动端可切换,桌面端永久显示)
你当前的问题出在两个核心点:
- sx样式里设置了
display: { xs: 'block', sm: 'none' },导致屏幕尺寸大于sm时Drawer直接被隐藏 - 没有区分移动端和桌面端的Drawer变体,且open状态未根据屏幕尺寸适配,桌面端需要永久显示,不能依赖mobileOpen状态
解决方案
借助MUI的useMediaQuery钩子判断屏幕尺寸,针对移动端和桌面端分别配置Drawer的变体、open状态和显示逻辑,同时添加移动端的菜单触发按钮。
修改后的完整代码
import React from "react"; import { useHistory } from "react-router-dom"; import { useMediaQuery, useTheme, makeStyles, Typography, Drawer, Toolbar, Divider, List, ListItem, ListItemText, ListItemIcon, Container, Box, IconButton } from "@material-ui/core"; import MenuIcon from '@material-ui/icons/Menu'; import HomeOutlinedIcon from '@material-ui/icons/HomeOutlined'; import AlternateEmailOutlinedIcon from '@material-ui/icons/AlternateEmailOutlined'; import NotificationsNoneOutlinedIcon from '@material-ui/icons/NotificationsNoneOutlined'; import DashboardOutlinedIcon from '@material-ui/icons/DashboardOutlined'; import ArchiveOutlinedIcon from '@material-ui/icons/ArchiveOutlined'; const drawerWidth = 280; const useStyles = makeStyles((theme) => ({ drawer: { width: drawerWidth, }, drawerPaper: { width: drawerWidth, }, list: { marginLeft: '24px', marginRight: '24px' }, listItem: { padding: '8px', borderRadius: '5px', }, text: { color: theme.palette.primary.light, fontWeight: '500', lineHeight: '2000' }, title: { color: theme.palette.primary.light, textAlign: 'center', display: 'block', fontWeight: '500', fontSize: '20px', marginTop: '10px', marginBottom: '10px' }, menuButton: { marginRight: theme.spacing(2), [theme.breakpoints.up('sm')]: { display: 'none', }, }, })); export default function LeftBar() { const classes = useStyles(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); const [mobileOpen, setMobileOpen] = React.useState(false); const handleDrawerToggle = () => { setMobileOpen(!mobileOpen); }; const list = [ { text: 'Home', icon: <HomeOutlinedIcon />, path: '/' }, { text: 'Personal', icon: <AlternateEmailOutlinedIcon />, path: '/' }, { text: 'Notificatons', icon: <NotificationsNoneOutlinedIcon />, path: '/' }, { text: 'Dashboard', icon: <DashboardOutlinedIcon />, path: '/' }, { text: 'Archives', icon: <ArchiveOutlinedIcon />, path: '/' } ]; return ( <Box> {/* 移动端菜单触发按钮 */} <Toolbar> <IconButton color="inherit" aria-label="open drawer" edge="start" onClick={handleDrawerToggle} className={classes.menuButton} > <MenuIcon /> </IconButton> </Toolbar> <Drawer className={classes.drawer} anchor="left" classes={{ paper: classes.drawerPaper }} // 桌面端永久打开,移动端由mobileOpen控制 open={isMobile ? mobileOpen : true} // 只有移动端需要关闭事件 onClose={isMobile ? handleDrawerToggle : undefined} // 根据屏幕尺寸选择变体:移动端用temporary,桌面端用permanent variant={isMobile ? 'temporary' : 'permanent'} ModalProps={{ keepMounted: true }} sx={{ // 桌面端始终显示,移动端不隐藏 display: { xs: 'block', sm: 'block' }, flexShrink: 0, '& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth }, }} > <Toolbar /> <Container> <Typography variant="h5" component="h2" className={classes.title} gutterBottom> My Account </Typography> </Container> <Divider /> <List className={classes.list}> {list.map((item) => ( <ListItem key={item.text} className={classes.listItem} button> <ListItemIcon className={classes.icon}> {item.icon} </ListItemIcon> <ListItemText sx={{ color: 'primary' }} primary={item.text} className={classes.text} /> </ListItem> ))} </List> </Drawer> </Box> ); };
关键修改点说明
- 引入
useMediaQuery和useTheme钩子,判断当前是否为移动端(屏幕尺寸≤sm) - 添加移动端专属的菜单触发按钮,桌面端自动隐藏
- 动态设置Drawer的
variant:移动端用temporary(可临时弹出),桌面端用permanent(永久显示) - 动态设置
open状态:桌面端始终为true,移动端由mobileOpen状态控制 - 修改sx的
display属性,确保桌面端Drawer不被隐藏 - 只有移动端需要设置
onClose事件,桌面端无需关闭逻辑
内容的提问来源于stack exchange,提问作者Morri
相关产品推荐
相关产品推荐

