【问题标题】:MaterialUI: Concise way to to define styled Components?Material UI:定义样式组件的简洁方法?
【发布时间】:2018-10-06 08:24:25
【问题描述】:

我想找到一种使用 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);

【问题讨论】:

    标签: reactjs typescript material-ui


    【解决方案1】:

    Material-UI Typescript guide 中找到了一些帮助我进行更好尝试的信息。

    感谢 Martin Hochel 的 Typescript pro tips 帖子让我开始使用类型交集将 WithStyles 混合到 Props 定义中(我一直在尝试使用 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>
      }
    });
    

    上面的一些问题:

    1. 重复withStyles(styles)WithStyles&lt;typeof styles&gt; 有点烦人。

    2. 状态定义中的属性名称也有一些轻微的重复,但它仍然比标准的构造函数安排好(无论如何你都重复属性名称,但至少需要多三行样板文件)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 2012-02-09
      • 1970-01-01
      • 2021-01-08
      • 2018-06-04
      • 2020-07-16
      • 2021-07-14
      相关资源
      最近更新 更多