我正在尝试将dahsboard的组件拆分为较小的组件。但是,所有组件均取决于抽屉宽度。我的第一个想法是将抽屉宽度移入状态,因此我可以将其传递到每个组件中。但是,变量样式取决于抽屉宽度。在学习material-ui文档和参考项目时,样式始终不在类之内。
我尝试将两个变量都移到类中,并通过类的引用将函数传递给withStyle,但这也失败了。页面的css已关闭,并且我收到一条警告,说我将无效的函数传递给withStyles。如下图所示。
export default withStyles(DashboardLayout.styles)(DashboardLayout);
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { withStyles } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
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 Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import Badge from '@material-ui/core/Badge';
import MenuIcon from '@material-ui/icons/Menu';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import NotificationsIcon from '@material-ui/icons/Notifications';
import { mainListItems, secondaryListItems } from './listItems';
const drawerWidth = 240;
const styles = theme => ({
root: {
display: 'flex',
},
toolbar: {
paddingRight: 24, // keep right padding when drawer closed
},
toolbarIcon: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: '0 8px',
...theme.mixins.toolbar,
},
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: {
marginLeft: 12,
marginRight: 36,
},
menuButtonHidden: {
display: 'none',
},
title: {
flexGrow: 1,
},
drawerPaper: {
position: 'relative',
whiteSpace: 'nowrap',
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
drawerPaperClose: {
overflowX: 'hidden',
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
width: theme.spacing.unit * 7,
[theme.breakpoints.up('sm')]: {
width: theme.spacing.unit * 9,
},
},
appBarSpacer: theme.mixins.toolbar,
content: {
flexGrow: 1,
padding: theme.spacing.unit * 3,
height: '100vh',
overflow: 'auto',
},
chartContainer: {
marginLeft: -22,
},
tableContainer: {
height: 320,
},
h5: {
marginBottom: theme.spacing.unit * 2,
},
});
class DashboardLayout extends React.Component {
state = {
open: true,
};
handleDrawerToggle = () => {
this.setState({ open: !this.state.open });
};
render() {
const { classes, children } = this.props;
return (
<div className={classes.root}>
<CssBaseline />
<AppBar
position="absolute"
className={classNames(classes.appBar, this.state.open && classes.appBarShift)}
>
<Toolbar disableGutters={!this.state.open} className={classes.toolbar}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerToggle}
className={classNames(
classes.menuButton,
this.state.open && classes.menuButtonHidden,
)}
>
<MenuIcon />
</IconButton>
<Typography
component="h1"
variant="h6"
color="inherit"
noWrap
className={classes.title}
>
Dashboard
</Typography>
<IconButton color="inherit">
<Badge badgeContent={4} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
classes={{
paper: classNames(classes.drawerPaper, !this.state.open && classes.drawerPaperClose),
}}
open={this.state.open}
>
<div className={classes.toolbarIcon}>
<IconButton onClick={this.handleDrawerToggle}>
<ChevronLeftIcon />
</IconButton>
</div>
<Divider />
<List>{mainListItems}</List>
<Divider />
</Drawer>
<main className={classes.content}>
{ this.props.children }
<div> Children </div>
</main>
</div>
);
}
}
DashboardLayout.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(DashboardLayout);
我想将抽屉,应用栏移动到它们自己的文件中,而不必在每个文件中硬编码抽屉宽度和样式。
答案 0 :(得分:2)
您可以将drawerWidth
放在自定义主题中,以便较小的组件可以从theme.drawerWidth
访问它。官方组件将使用theme's values against some specific keys(即palette
),但是您始终可以为自己的组件添加更多密钥。 Docs on themes
例如,使用createMuiTheme
创建一个主题并将其作为道具传递给MuiThemeProvider
:
const theme = createMuiTheme({
drawerWidth: 200 // a custom key in theme object
});
function Root() {
return (
<MuiThemeProvider theme={theme}>
<App/>
</MuiThemeProvider>
);
}
现在,您可以使用drawerWidth
从较小组件中的theme
访问withStyles
,例如:
// your appbar's own style
const styles = theme => ({
appBar: {
width: `calc(100% - ${theme.drawerWidth}px)`,
marginLeft: theme.drawerWidth
}
})
export default withStyles(styles)(YourAppBar);
// your drawer's own style
const styles = theme => ({
drawer: {
width: theme.drawerWidth,
flexShrink: 0
},
drawerPaper: {
width: theme.drawerWidth
}
})
export default withStyles(styles)(YourDrawer);
以下是沙箱中的一个示例:https://codesandbox.io/s/7j4y8p6nox