Material UI - 响应式抽屉

问题描述 投票:0回答:5

有谁知道如何,或者知道如何创建反应式

Appbar
Drawer
的任何示例吗?

它需要能够在浏览器较小时动态取消停靠抽屉并隐藏,并在浏览器较大时停靠抽屉,最好像 Material UI 网站一样动态:https://mui.com/material-ui/反应抽屉/

reactjs mobile responsive-design material-design material-ui
5个回答
17
投票

对于那些使用 Material-UI V1 及更高版本的人来说,使用 断点 是制作响应式布局的最佳方法。

断点:

  • xs,超小:0px 或更大
  • sm,小:600px 或更大
  • md,中:960px 或更大
  • lg,大:1280px 或更大
  • xl、xlarge:1920px 或更大

因此,要更改 React 渲染树,您应该将不同的断点参数值传递到 JSS 中的

breakpoints.up()

navIconHide: {
    [theme.breakpoints.up('md')]: {
      display: 'none',
    },
  },
  toolbar: theme.mixins.toolbar,
  drawerPaper: {
    width: drawerWidth,
    [theme.breakpoints.up('md')]: {
      position: 'relative',
    },
  },

整个Drawer源代码如下。

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } 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 Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import Hidden from '@material-ui/core/Hidden';
import Divider from '@material-ui/core/Divider';
import MenuIcon from '@material-ui/icons/Menu';
import { mailFolderListItems, otherMailFolderListItems } from './tileData';

const drawerWidth = 240;

const styles = theme => ({
  root: {
    flexGrow: 1,
    height: 430,
    zIndex: 1,
    overflow: 'hidden',
    position: 'relative',
    display: 'flex',
    width: '100%',
  },
  appBar: {
    position: 'absolute',
    marginLeft: drawerWidth,
    [theme.breakpoints.up('md')]: {
      width: `calc(100% - ${drawerWidth}px)`,
    },
  },
  navIconHide: {
    [theme.breakpoints.up('md')]: {
      display: 'none',
    },
  },
  toolbar: theme.mixins.toolbar,
  drawerPaper: {
    width: drawerWidth,
    [theme.breakpoints.up('md')]: {
      position: 'relative',
    },
  },
  content: {
    flexGrow: 1,
    backgroundColor: theme.palette.background.default,
    padding: theme.spacing.unit * 3,
  },
});

class ResponsiveDrawer extends React.Component {
  state = {
    mobileOpen: false,
  };

  handleDrawerToggle = () => {
    this.setState(state => ({ mobileOpen: !state.mobileOpen }));
  };

  render() {
    const { classes, theme } = this.props;

    const drawer = (
      <div>
        <div className={classes.toolbar} />
        <Divider />
        <List>{mailFolderListItems}</List>
        <Divider />
        <List>{otherMailFolderListItems}</List>
      </div>
    );

    return (
      <div className={classes.root}>
        <AppBar className={classes.appBar}>
          <Toolbar>
            <IconButton
              color="inherit"
              aria-label="Open drawer"
              onClick={this.handleDrawerToggle}
              className={classes.navIconHide}
            >
              <MenuIcon />
            </IconButton>
            <Typography variant="title" color="inherit" noWrap>
              Responsive drawer
            </Typography>
          </Toolbar>
        </AppBar>
        <Hidden mdUp>
          <Drawer
            variant="temporary"
            anchor={theme.direction === 'rtl' ? 'right' : 'left'}
            open={this.state.mobileOpen}
            onClose={this.handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden smDown implementation="css">
          <Drawer
            variant="permanent"
            open
            classes={{
              paper: classes.drawerPaper,
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <main className={classes.content}>
          <div className={classes.toolbar} />
          <Typography noWrap>{'You think water moves fast? You should see ice.'}</Typography>
        </main>
      </div>
    );
  }
}

ResponsiveDrawer.propTypes = {
  classes: PropTypes.object.isRequired,
  theme: PropTypes.object.isRequired,
};

export default withStyles(styles, { withTheme: true })(ResponsiveDrawer);

9
投票

您可以像这样在 componentWillMount 中监听屏幕尺寸的变化,我确信有更好的方法,但这可行。

toggleOpenDrawer = () => {
    if (!this.state.mobile) {
        return;
    }
    this.setState({
        open: !this.state.open
    })
}

setSmall = () => {
    this.setState({open: false, docked: false, mobile: true})
}

setLarge = () => {
    this.setState({open: true, docked: true, mobile: false})
}

componentWillMount() {
  const mediaQuery = window.matchMedia('(min-width: 768px)');
  if (mediaQuery.matches) {
    this.setLarge()
  } else {
    this.setSmall()
  }
  mediaQuery.addListener((mq) => {
    if (mq.matches) {
      this.setLarge()
    } else {
      this.setSmall()
    }
  });
}

5
投票

MUI v5中,您可以在不同的屏幕尺寸中显示2个

Drawers
永久
Drawer
在大屏幕中始终可见。在小屏幕中,您可以使用 sx 属性中的
响应值
轻松删除它:

<Drawer
  variant="permanent"
  open
  sx={{ display: { xs: 'none', sm: 'block' } }}
>

并显示一个可以打开或关闭的临时

Drawer
。临时的不会影响布局,因为它出现在顶部,适合移动视图。

<Drawer
  variant="temporary"
  open={mobileOpen}
  onClose={handleDrawerToggle}
  sx={{ display: { xs: 'block', sm: 'none' } }}
>

现场演示

Codesandbox Demo

参考


0
投票

我同意NearHuscarl的观点,如果你想使用媒体查询,应该像这样smt:

 sx={{
      ['@media (min-width: 0px)']: {
        display: 'block',
      },
      ['@media (min-width: 600px)']: {
        display: 'none',
      },
      '& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
    }}

0
投票

您可以使用

useMediaQuery
挂钩

const matches = useMediaQuery("(min-width:768px)");

<Drawer
  variant={matches ? "permanent" : "temporary"}
  ...
</Drawer>
© www.soinside.com 2019 - 2024. All rights reserved.