Reactjs 材质UI中垂直间距的框与类名与样式

Reactjs 材质UI中垂直间距的框与类名与样式,reactjs,material-ui,Reactjs,Material Ui,当我看到一个使用Material UI实现的设计时,在节标题、表单标签、输入字段等之间总是有一些垂直空间。似乎有几种方法可以实现这一点: 将每个,等包装在中 为每个元素创建一个具有间距的类,例如 对于第二个类,您最终创建了许多相当无意义的类,以适应纯粹出于设计/美学原因而非语义原因在每个元素下需要不同的间距,例如带有marginBottom:2的类和带有marginBottom:3的类 第三个选项似乎很有意义,因为将间隔逻辑提取到可重用代码中似乎有些过分,但内联样式通常不受欢迎,而且在每个组件中

当我看到一个使用Material UI实现的设计时,在节标题、表单标签、输入字段等之间总是有一些垂直空间。似乎有几种方法可以实现这一点:

  • 将每个
    等包装在
  • 为每个元素创建一个具有间距的类,例如
  • 对于第二个类,您最终创建了许多相当无意义的类,以适应纯粹出于设计/美学原因而非语义原因在每个元素下需要不同的间距,例如带有
    marginBottom:2
    的类和带有
    marginBottom:3
    的类

    第三个选项似乎很有意义,因为将间隔逻辑提取到可重用代码中似乎有些过分,但内联样式通常不受欢迎,而且在每个组件中调用
    const-theme=useTheme()
    似乎并不正确

    TLDR
    在材质UI中垂直间隔组件的推荐方式是什么?

    我建议使用
    框的道具。这会导致它将样式添加到其子级(通过
    React.cloneElement
    ),而不是用额外的元素包装它

    下面的示例在第一个排版中添加了下边距,在第二个排版中添加了左边距,而没有在html中引入任何额外的包装器元素

    import React from "react";
    import Typography from "@material-ui/core/Typography";
    import Box from "@material-ui/core/Box";
    
    export default function App() {
      return (
        <>
          <Box mb={3} clone>
            <Typography variant="h5" color="primary">
              Some Text
            </Typography>
          </Box>
          <Box ml={2} clone>
            <Typography color="primary">Later Text</Typography>
          </Box>
        </>
      );
    }
    
    然后可以按如下方式使用:

    import React from "react";
    import Typography from "./TypographyWithMargin";
    
    export default function App() {
      return (
        <>
          <Typography mb={3} variant="h5" color="primary">
            Some Text
          </Typography>
          <Typography ml={2} color="primary">
            Later Text
          </Typography>
        </>
      );
    }
    
    从“React”导入React;
    从“/TypographyWithMargin”导入排版;
    导出默认函数App(){
    返回(
    一些文本
    后文
    );
    }
    

    我已经申请了海登·皮克林的职位

    我创建了一个组件
    Vertical.js

    import React from 'react';
    import { makeStyles } from '@material-ui/core/styles';
    import { Box } from '@material-ui/core';
    
    const useStyles = makeStyles((theme) => ({
      vertical: {
        '& > *+*': {
          marginTop: '1.5rem',
        },
      },
    }));
    
    const Vertical = ({ children }) => {
      const classes = useStyles();
      return <Box className={classes.vertical}>{children}</Box>;
    };
    
    export default Vertical;
    
    从“React”导入React;
    从'@material ui/core/styles'导入{makeStyles};
    从'@material ui/core'导入{Box};
    const useStyles=makeStyles((主题)=>({
    垂直:{
    '& > *+*': {
    marginTop:“1.5雷姆”,
    },
    },
    }));
    常量垂直=({children})=>{
    const classes=useStyles();
    返回{children};
    };
    导出默认垂直;
    
    然后在任何其他组件中使用它,例如Example.js:

    import React from 'react';
    import Vertical from './Vertical';
    
    const Example = () => {
      return (
        <Vertical>
          <Component/>
          <Component />
          <Another />
          <AnotherComponent />
        </Vertical>
      );
    };
    
    export default Example;
    
    从“React”导入React;
    从“./垂直”导入垂直;
    常量示例=()=>{
    返回(
    );
    };
    导出默认示例;
    
    我不知道克隆的事。看起来是个干净的选择。在接受之前,我会再给它一些时间,看看是否有更多的答案。由于.MuiTypography root setting
    margin bottom:0,我在实现此答案时遇到问题并优先。我怀疑这是由于此处解释的进口顺序所致:。订购进口商品的推荐解决方案对我不起作用。我怀疑Next.js在改变顺序。我怀疑Next.js在改变顺序,但你必须注意整个应用程序中的顺序,而不仅仅是一个文件。如果第一次导入该框的时间早于第一次导入排版,那么排版将获胜。@jjt我添加了一个替代解决方案,用于使用
    clone
    属性的
    Box
    无法正常工作的情况。谢谢@Ryan,我非常感谢后续解决方案。期待着烘焙解决方案。
    import * as React from "react";
    import Typography from "@material-ui/core/Typography";
    import { makeStyles } from "@material-ui/core/styles";
    import clsx from "clsx";
    
    const useStyles = makeStyles(theme => ({
      margin: ({ mb, mt, ml, mr }) => ({
        marginBottom: mb === undefined ? undefined : theme.spacing(mb),
        marginTop: mt === undefined ? undefined : theme.spacing(mt),
        marginLeft: ml === undefined ? undefined : theme.spacing(ml),
        marginRight: mr === undefined ? undefined : theme.spacing(mr)
      })
    }));
    
    const TypographyWithMargin = React.forwardRef(function TypographyWithMargin(
      { className, mb, ml, mt, mr, ...other },
      ref
    ) {
      const classes = useStyles({ mb, ml, mt, mr });
      return (
        <Typography
          {...other}
          className={clsx(className, classes.margin)}
          ref={ref}
        />
      );
    });
    export default TypographyWithMargin;
    
    import React from "react";
    import Typography from "./TypographyWithMargin";
    
    export default function App() {
      return (
        <>
          <Typography mb={3} variant="h5" color="primary">
            Some Text
          </Typography>
          <Typography ml={2} color="primary">
            Later Text
          </Typography>
        </>
      );
    }
    
    import React from 'react';
    import { makeStyles } from '@material-ui/core/styles';
    import { Box } from '@material-ui/core';
    
    const useStyles = makeStyles((theme) => ({
      vertical: {
        '& > *+*': {
          marginTop: '1.5rem',
        },
      },
    }));
    
    const Vertical = ({ children }) => {
      const classes = useStyles();
      return <Box className={classes.vertical}>{children}</Box>;
    };
    
    export default Vertical;
    
    import React from 'react';
    import Vertical from './Vertical';
    
    const Example = () => {
      return (
        <Vertical>
          <Component/>
          <Component />
          <Another />
          <AnotherComponent />
        </Vertical>
      );
    };
    
    export default Example;