首页 > 解决方案 > Material UI Drawer 组件中如何包含主组件的宽度?

问题描述

我正在尝试在 Material UI 中使用抽屉。

我希望主 div 的宽度在菜单抽屉使用其空间后占用视口中剩余的任何可用空间。

这是我的组件。我尝试将宽度设置为自动并在内容类上继承,但它不会改变任何东西。

我希望渲染主 div(抽屉中列表项的内容),以便在不水平滚动的情况下只占用尽可能多的可用空间。

此代码沙箱显示问题:https ://codesandbox.io/s/material-tab-scrolling-h13pi?file=/test.jsx

import React, {  useState, useEffect } from 'react';
import { Switch, Route, Link, BrowserRouter } from "react-router-dom";
import clsx from 'clsx';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import List from '@material-ui/core/List';
import CssBaseline from '@material-ui/core/CssBaseline';
import Typography from '@material-ui/core/Typography';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import Container from '@material-ui/core/Container'

import MenuIcon from '@material-ui/icons/Menu';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import MailIcon from '@material-ui/icons/Mail';
import AccountCircle from '@material-ui/icons/AccountCircle';
import PaletteIcon from '@material-ui/icons/Palette';
import CenterFocusWeakIcon from '@material-ui/icons/CenterFocusWeak';
import RoomServiceIcon from '@material-ui/icons/RoomService';
import StorefrontIcon from '@material-ui/icons/Storefront';
import AssignmentIcon from '@material-ui/icons/Assignment';
import NotificationsIcon from '@material-ui/icons/Notifications';
import AccountBoxIcon from '@material-ui/icons/AccountBox';
import ContactSupportIcon from '@material-ui/icons/ContactSupport';
import BookIcon from '@material-ui/icons/Book';
import TuneIcon from '@material-ui/icons/Tune';
import SettingsIcon from '@material-ui/icons/Settings';
import CloseIcon from '@material-ui/icons/Close';
import DashboardFooter from "./DashboardFooter";

const drawerWidth = 240;

const useStyles = makeStyles((theme) => ({
  root: {
    display: 'flex',
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
    transition: theme.transitions.create(['width', 'margin'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
  },
  appBarShift: {
    marginLeft: drawerWidth,
    width: `calc(100% - ${drawerWidth}px)`,
    transition: theme.transitions.create(['width', 'margin'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  menuButton: {
    marginRight: 36,
  },
  hide: {
    display: 'none',
  },
  drawer: {
    width: drawerWidth,
    flexShrink: 0,
    whiteSpace: 'nowrap',
  },
  drawerOpen: {
    width: drawerWidth,
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  drawerClose: {
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    overflowX: 'hidden',
    width: theme.spacing(7) + 1,
    [theme.breakpoints.up('sm')]: {
      width: theme.spacing(9) + 1,
    },
  },
  toolbar: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 1),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar,
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing(3),
    // autoWidth: false
    
  },
  container: {
    paddingTop: theme.spacing(4),
    paddingBottom: theme.spacing(4),
  },
}));

export default function MiniDrawer() {
  const classes = useStyles();
  const theme = useTheme();
  const [open, setOpen] = React.useState(false);
 //   const { performingAction, user, userData, roles } = this.props;

  
  const handleDrawerOpen = () => {
    setOpen(true);
  };

  const handleDrawerClose = () => {
    setOpen(false);
  };
 
  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar
        position="fixed"
        className={clsx(classes.appBar, {
          [classes.appBarShift]: open,
        })}
      >
        <Toolbar>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            onClick={handleDrawerOpen}
            edge="start"
            className={clsx(classes.menuButton, {
              [classes.hide]: open,
            })}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            {process.env.REACT_APP_TITLE}
            
          </Typography>
            
          <IconButton color="inherit"><CloseIcon /></IconButton>    
        </Toolbar>
      </AppBar>
      <BrowserRouter>
        <Drawer
            variant="permanent"
            className={clsx(classes.drawer, {
            [classes.drawerOpen]: open,
            [classes.drawerClose]: !open,
            })}
            classes={{
            paper: clsx({
                [classes.drawerOpen]: open,
                [classes.drawerClose]: !open,
            }),
            }}
        >
            <div className={classes.toolbar}>
            <IconButton onClick={handleDrawerClose}>
                {theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
            </IconButton>
            </div>
            
            <List>
            
                <ListItem button key="1" component={Link} to={"/DSM" }>
                    <ListItemIcon><PaletteIcon /></ListItemIcon>
                    <ListItemText primary="DS"></ListItemText> 
                </ListItem>
                <ListItem button key="2" component={Link} to={"/MMM" }>
                    <ListItemIcon><CenterFocusWeakIcon /></ListItemIcon>
                    <ListItemText>MM</ListItemText> 
                </ListItem>
                <ListItem button key="3" component={Link} to={"/RCM" }>
                    <ListItemIcon><StorefrontIcon /></ListItemIcon>
                    <ListItemText>Centre</ListItemText> 
                </ListItem>
                <ListItem button key="4" component={Link} to={"/TT" }>
                    <ListItemIcon><AssignmentIcon /></ListItemIcon>
                    <ListItemText>TT</ListItemText> 
                </ListItem>
                
            </List>
            <Divider />
            <List>
                <ListItem button key="5"  component={Link} to={"/Profile" }>
                <ListItemIcon> <AccountBoxIcon /></ListItemIcon>
                <ListItemText>Profile</ListItemText> 
                </ListItem>
                <ListItem button key="6"  component={Link} to={"/Account" }>
                <ListItemIcon> <SettingsIcon /></ListItemIcon>
                <ListItemText>Account</ListItemText> 
                </ListItem>
                <ListItem button key="7"  component={Link} to={"/Mail" }>
                <ListItemIcon> <MailIcon /></ListItemIcon>
                <ListItemText>Mail</ListItemText> 
                </ListItem>
                <ListItem button key="8"  component={Link} to={"/Notifications" }>
                <ListItemIcon> <NotificationsIcon /></ListItemIcon>
                <ListItemText>Notifications</ListItemText>
                </ListItem>
            
            </List>
            <Divider />
            <List>
                
                <ListItem button key="9"  component={Link} to={"/CM" }>
                    <ListItemIcon> <BookIcon /></ListItemIcon>
                    <ListItemText>Centre</ListItemText> 
                </ListItem>
                <ListItem button key="10"  component={Link} to={"/DCM" }>
                    <ListItemIcon><RoomServiceIcon /></ListItemIcon>
                    <ListItemText>Desk</ListItemText> 
                </ListItem>
                <ListItem button key="11"  component={Link} to={"/Support" }>
                <ListItemIcon> <ContactSupportIcon /></ListItemIcon>
                <ListItemText>Help and Support</ListItemText>
                </ListItem>
            
            
            </List>
        </Drawer>
        <main className={classes.content}>
          <div className={classes.toolbar} />

            <Switch>
                <Route path="/DCM" component={""} />
                <Route path="/MMM" render={() => <div>Page mm</div>} />
            </Switch>
            <DashboardFooter />
        </main>
     </BrowserRouter>   
     
    </div>
      
      
  );
}

标签: reactjsmaterial-ui

解决方案


主要问题是 dash.jsx 中的以下内容:

  root: {
    display: 'flex',
  },

这在某种程度上破坏了Tabs其“可滚动选项卡”功能的机制,并导致Tabs占用显示其所有选项卡按钮而不是显示滚动按钮所需的宽度。display: 'flex'让管理内容宽度变得更容易(这样它会根据抽屉宽度自动调整),但用其他方式管理它并不难。

备选方案 1

在我修改过的沙箱版本中,为了修复display: 'flex'从根目录中删除的效果,我将 padding-left 添加到与抽屉宽度相同的内容中:

  content: {
    padding: theme.spacing(3),
    paddingLeft: theme.spacing(7) + 1,
    [theme.breakpoints.up("sm")]: {
      paddingLeft: theme.spacing(9) + 1
    }
  },
  contentDrawerOpen: {
    paddingLeft: drawerWidth
  },
...
<main className={clsx(classes.content, {[classes.contentDrawerOpen]: open})}>

编辑材料选项卡滚动


备选方案 2

另一种选择是离开display: 'flex',但max-width在内容上适当地指定。

  content: {
    padding: theme.spacing(3),
    maxWidth: `calc(100vw - ${theme.spacing(7) + 1}px)`,
    [theme.breakpoints.up("sm")]: {
      maxWidth: `calc(100vw - ${theme.spacing(9) + 1}px)`
    }
  },
  contentDrawerOpen: {
    maxWidth: `calc(100vw - ${drawerWidth}px)`
  },

编辑材料选项卡滚动


备选方案 3(受 Ahmed Mokhtar 的回答启发)

将元素添加overflow: "auto"content类中似乎也足够了:<main>

  content: {
    padding: theme.spacing(3),
    overflow: "auto"
  },

编辑材料选项卡滚动

最后一种选择绝对是最简单的。


推荐阅读