材质UI中垂直间距的Box,ClassName和Style [英] Box vs className vs style for vertical spacing in Material UI

查看:94
本文介绍了材质UI中垂直间距的Box,ClassName和Style的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  1. 将每个<排版/> <复选框/> 等包装在< Box paddingBottom = {2}/> .
  2. 为每个具有间距的元素创建一个类,例如

  const useStyles = makeStyles(theme =>({subHeader:{marginBottom:theme.spacing(2)}}));...const classes = useStyles();...< Typography className = {classes.subHeader}/> 

  1. 使用内联样式,例如

  const theme = useTheme();<版式样式= {{marginBottom:theme.spacing(2)}}/> 

这些方法中的每一种在我看来都不对.

第一个在您的HTML代码中添加了许多额外的 div ,并保证相邻的概念元素永远不会相邻;它们总是嵌套的.

 < div class ="MuiBox-root">< span class ="MuiTypography-root"/></div>< div class ="MuiBox-root"><span class="MuiTypography-root";/></div> 

在第二个步骤中,您最终创建了许多相当无意义的类,以适应纯粹出于设计/审美原因而非语义原因而需要在每个元素下方放置不同间距的问题,例如具有 marginBottom:2 的类,还有一个 marginBottom:3 .

第三个选项似乎很有意义,因为将间距逻辑提取到可重用的代码中似乎是多余的,但是内联样式通常不被接受,并且必须在每个组件中调用 const theme = useTheme()似乎不正确.

TLDR; 在Material UI中垂直间隔组件的推荐方法是什么?

解决方案

我建议使用

不幸的是,如注释中所述,当 Box <设置的样式之间存在重叠时,使用 Box clone 道具可能很脆弱./code>以及由包装后的组件设置的样式(例如 Typography ),因为导入顺序会影响一个获胜者(而不只是您关注的特定文件中的导入顺序),而是它们在应用中的首次导入顺序.

针对这些情况的一种解决方案是创建自己的包装器组件,以模仿要经常使用的 Box 中的功能.例如,下面是一个可以代替 Typography 来以类似Box的方式控制边距的组件:

  import *作为来自"react"的React;从"@ material-ui/core/Typography"导入字体;从"@ material-ui/core/styles"导入{makeStyles};从"clsx"导入clsx;const useStyles = makeStyles(theme =>({保证金:({mb,mt,ml,mr})=>({marginBottom:mb ===未定义?未定义:theme.spacing(mb),marginTop: mt === 未定义?未定义:theme.spacing(mt),marginLeft:ml ===未定义?未定义:theme.spacing(ml),marginRight:先生===未定义?未定义:theme.spacing(mr)})}));const TypographyWithMargin = React.forwardRef(函数TypographyWithMargin({className,mb,ml,mt,mr,... other},参考){const classes = useStyles({mb,ml,mt,mr});返回 (<印刷术{...其他}className={clsx(className, classes.margin)}ref = {ref}/>);});导出默认的TypographyWithMargin; 

然后可以按以下方式使用:

  import从"react"导入React;从"./TypographyWithMargin"导入印刷术;导出默认函数App(){返回 (<><版式mb = {3}变体="h5";color =原色">一些文字</Typography><印刷术ml = {2} color =原色">后来的文字</Typography></>);} 

When I am presented with a design to implement using Material UI there is invariably some vertical space between section headers, form labels, input fields, etc. There seem to be a few ways to achieve this:

  1. Wrap each <Typography />, <Checkbox />, etc. in a <Box paddingBottom={2} />.
  2. Create a class for each element with the spacing, e.g.

const useStyles = makeStyles(theme => ({ subHeader: { marginBottom: theme.spacing(2) } }));
...
const classes = useStyles();
...
<Typography className={classes.subHeader} />

  1. Use inline styles, e.g.

const theme = useTheme();
<Typography style={{ marginBottom: theme.spacing(2) }} />

Each of these approaches doesn't seem right to me.

The first adds a lot of extra divs to your HTML code and guarantees that adjacent conceptual elements are never adjacent; they are always nested.

<div class="MuiBox-root">
  <span class="MuiTypography-root" />
</div>
<div class="MuiBox-root">
  <span class="MuiTypography-root" />
</div>

With the second you end up creating lots of fairly meaningless classes to accommodate needing different spacing below each element for purely design/aesthetic reasons, not semantic reasons, such as a class with marginBottom: 2, and one with marginBottom: 3.

The third option seems to make sense as extracting out spacing logic into reusable code seems overkill, but inline styles are generally frowned upon, and having to call const theme = useTheme() in every component doesn't seem right.

TLDR; What is the recommended way for spacing components vertically in Material UI?

解决方案

I would recommend using the clone prop of Box. This causes it to add the styles to its child (via React.cloneElement) rather than wrapping it with an extra element.

The example below adds bottom margin to the first Typography and left margin to the second without introducing any additional wrapper elements in the 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>
    </>
  );
}

Unfortunately, as discussed in the comments, using the clone prop of Box can be brittle when there is overlap between the styles being set by the Box and the styles being set by the wrapped component (e.g. Typography) since then the order of import impacts which one wins (and not just the order of import in the particular file you are focusing on, but rather the order of their first import in the app).

One solution for these cases is to create your own wrapper component to imitate the functionality in Box that you want to use frequently. For instance, below is a component that can be used in place of Typography to control margin in a Box-like fashion:

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;

and then this can be used as follows:

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>
    </>
  );
}

这篇关于材质UI中垂直间距的Box,ClassName和Style的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆