MUI - 响应式抽屉

Posted

技术标签:

【中文标题】MUI - 响应式抽屉【英文标题】:MUI - Responsive Drawer 【发布时间】:2017-08-02 15:48:54 【问题描述】:

有谁知道如何创建响应式AppbarDrawer,或者知道如何创建响应式Drawer 的示例?

它需要能够在浏览器较小时动态取消停靠抽屉并隐藏,并在浏览器较大时停靠抽屉,最好像 MUI 网站那样动态:https://mui.com/components/drawers

【问题讨论】:

您可以使用material-ui-responsive-drawer:npmjs.com/package/material-ui-responsive-drawer 示例:tarikhuber.github.io/material-ui-responsive-drawer 【参考方案1】:

您可以像这样在 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()
    
  );

【讨论】:

【参考方案2】:

对于使用 Material-UI V1 及更高版本的用户,使用breakpoints 是制作响应式布局的最佳方式。

断点:

xs,超小:0px 或更大 sm, small: 600px 或更大 md, medium: 960px 或更大 lg, large: 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 source code如下。

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% - $drawerWidthpx)`,
    ,
  ,
  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);

【讨论】:

【参考方案3】:

MUI v5中,您可以在不同的屏幕尺寸下显示2个Drawers。 permanent Drawer 在大屏幕中始终可见。在小屏幕中,您可以使用 responsive values in sx prop 轻松删除它:

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

并显示一个可以打开或关闭的temporary Drawer。临时的不影响布局,因为它显示在顶部,适合移动视图。

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

现场演示

参考

https://mui.com/components/drawers/#responsive-drawer

【讨论】:

以上是关于MUI - 响应式抽屉的主要内容,如果未能解决你的问题,请参考以下文章

MUI体验框架

响应式编程与响应式系统

什么是响应式网站及其特点

H5响应式布局 响应式图片 响应式布局网站怎么写?

响应式编程详解,带你熟悉Reactor响应式编程

网页设计中响应式具体怎么实现?