我想找到一种使用Material-UI在我的应用中轻松定义便利组件的方法。
我从Material-UI doco for Appbar复制了一个示例,并尝试引入一些React组件以提高可读性。
我的问题是关于MenuShortcutBar
函数和下面的MenuShortcutItem
类之间的样板对比。
MenuShortcutBar
非常简洁;但是,一旦Material-UI样式出现,我最终就需要大量样板。我必须定义一个类,一个需要扩展WithStyles
的属性接口和一个构造函数。
问题是:使用Material-UI时是否有一种简洁的方法来创建样式化的React组件?如何简化MenuShortcutItem
?
import * as React from "react";
import {ReactNode, SyntheticEvent} from "react";
import {
AppBar,
Hidden,
IconButton,
Menu,
MenuItem,
SvgIcon,
Toolbar,
Typography,
withStyles,
WithStyles
} from "@material-ui/core";
import {SvgIconProps} from "@material-ui/core/SvgIcon";
import {SendMailSvg} from "component/svg-icon/SendMailSvg";
export interface MuiAppBarProps extends WithStyles<typeof styles> {
}
class MuiAppBar extends React.Component<
MuiAppBarProps,
{ anchorEl?: HTMLElement, }
>{
constructor(props: MuiAppBarProps, context?: any){
super(props, context);
this.state = {anchorEl: undefined}
}
handleMenu = (event:SyntheticEvent<HTMLElement>) => {
this.setState({ anchorEl: event.currentTarget });
};
handleClose = () => {
this.setState({ anchorEl: undefined });
};
render(){
const { classes } = this.props;
return <div className={classes.root}>
<AppBar position="static" color={"default"}>
<Toolbar variant={"dense"}>
<IconButton className={classes.menuButton} color="inherit">
<MenuIcon/>
</IconButton>
<IconButton className={classes.menuButton} color="inherit">
<SendMailSvg width={"2em"}/>
</IconButton>
<MenuShortcutBar>
<MenuShortcutItem classes={this.props.classes}>
Keywords
</MenuShortcutItem>
<MenuShortcutItem classes={this.props.classes}>
Forwarded
</MenuShortcutItem>
<MenuShortcutItem classes={this.props.classes}>
Rejected
</MenuShortcutItem>
</MenuShortcutBar>
</Toolbar>
</AppBar>
</div>
}
}
...
function MenuShortcutBar(props:{children: ReactNode}){
return <Hidden smDown>
{/* Avoid shortcuts wrapping which causes AppBar to grow in height */}
<span style={{
display: "flex", flexWrap: "nowrap", overflow: "hidden"
}}>
{props.children}
</span>
</Hidden>
}
interface MenuShortcutItemProps extends WithStyles<typeof styles> {
children: React.ReactNode
}
class MenuShortcutItem extends React.Component<
MenuShortcutItemProps,
any
>{
constructor(props: MenuShortcutItemProps, context?: any){
super(props, context);
}
render(){
return <IconButton color="inherit"
className={this.props.classes.menuButton}
>
{this.props.children}
</IconButton>
}
}
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
export default withStyles(styles)(MuiAppBar);
答案 0 :(得分:1)
在Material-UI Typescript guide中找到了一些有助于我更好地尝试的信息。
感谢Martin Hochel的Typescript pro tips帖子,使我开始使用类型交集将nodeservice
混合到Props定义中(我很想尝试使用WithStyles
)。
更简洁的函数式定义:
extends
还有一个相当简洁的类样式组件定义,用于定义何时需要状态:
const MenuShortcutItem2 = withStyles(styles)((
props:{children:ReactNode} & WithStyles<typeof styles>
) => (
<IconButton className={props.classes.menuButton} color="inherit">
{props.children}
</IconButton>
));
以上问题:
重复const ScreenContainer = withStyles(style)(class extends React.Component<
{children:ReactNode} & WithStyles<typeof style>
>{
state = {message: "wibble"} as {message?: string};
render(){
return <main className={this.props.classes.mainLayout}>
<Paper className={this.props.classes.paper}>
{this.props.children}
{this.state.message}
</Paper>
</main>
}
});
和withStyles(styles)
时出现的重复令人讨厌。
在状态定义中,属性名称也有一些重复,但这仍然比标准的构造函数安排好(无论如何,您都要复制属性名称,但至少需要三行样板)。