代码之家  ›  专栏  ›  技术社区  ›  Shorn

MaterialUI:定义样式化组件的简明方法?

  •  3
  • Shorn  · 技术社区  · 6 年前

    我从报纸上抄了一个例子 Material-UI doco for Appbar

    MenuShortcutBar 功能和 MenuShortcutItem 下课。

    菜单快捷工具栏 相当简洁;但一旦材料界面样式进入它,我最终需要很多样板。我必须定义一个类,一个需要扩展的属性接口 WithStyles 还有一个构造器。

    所以问题是:在使用materialui时,有没有一种简洁的方法来创建样式化的React组件?如何简化 ?

    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);
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Shorn    6 年前

    Material-UI Typescript guide 这让我有了更好的尝试。

    感谢马丁·霍切尔的帮助 Typescript pro tips 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>
      }
    });
    

    1. withStyles(styles) WithStyles<typeof styles> 有点烦人。

    2. 在state的定义中,属性名也有一些轻微的重复,但是它仍然比标准的构造函数安排好(在这里您仍然复制了属性名,但是至少还需要三行样板文件)。