是否可以将函数传递到组件内部的 Material-UI withStyles()
Is it possible to move the functions pass into Material-UI withStyles() inside the component
我正在尝试将仪表板的组件拆分为更小的组件。但是,所有组件都依赖于 drawerWidth。我的第一个想法是让 drawerWidth 进入状态,这样我就可以将它传递给每个组件。但是,可变样式取决于 drawerWidth。在研究 material-ui 文档和参考项目时,样式总是在 class.
之外
我尝试将两个变量都移到 class 中,并通过 class 的引用将函数传递给 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);
我想将抽屉、appbar 移动到它们自己的文件中,而不必在每个文件中对 drawerWidth 和样式进行硬编码。
您可以将 drawerWidth
放入您的自定义主题中,以便您的较小组件可以从 theme.drawerWidth
访问它。官方组件将使用theme's values against some specific keys (i.e. palette
), but you can always add more keys for your own components. Docs on themes
例如,使用 createMuiTheme
创建一个主题并将其作为 prop 传递给 MuiThemeProvider
:
const theme = createMuiTheme({
drawerWidth: 200 // a custom key in theme object
});
function Root() {
return (
<MuiThemeProvider theme={theme}>
<App/>
</MuiThemeProvider>
);
}
现在您可以使用 withStyles
从 theme
访问 drawerWidth
,例如:
// 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
我正在尝试将仪表板的组件拆分为更小的组件。但是,所有组件都依赖于 drawerWidth。我的第一个想法是让 drawerWidth 进入状态,这样我就可以将它传递给每个组件。但是,可变样式取决于 drawerWidth。在研究 material-ui 文档和参考项目时,样式总是在 class.
之外我尝试将两个变量都移到 class 中,并通过 class 的引用将函数传递给 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);
我想将抽屉、appbar 移动到它们自己的文件中,而不必在每个文件中对 drawerWidth 和样式进行硬编码。
您可以将 drawerWidth
放入您的自定义主题中,以便您的较小组件可以从 theme.drawerWidth
访问它。官方组件将使用theme's values against some specific keys (i.e. palette
), but you can always add more keys for your own components. Docs on themes
例如,使用 createMuiTheme
创建一个主题并将其作为 prop 传递给 MuiThemeProvider
:
const theme = createMuiTheme({
drawerWidth: 200 // a custom key in theme object
});
function Root() {
return (
<MuiThemeProvider theme={theme}>
<App/>
</MuiThemeProvider>
);
}
现在您可以使用 withStyles
从 theme
访问 drawerWidth
,例如:
// 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