Material UI 5 类名称样式

Tom*_*Tom 22 css emotion reactjs material-ui css-in-js

我从 Mui 4 迁移到 5,想知道如何使用类名。如果我想将某些样式仅应用于一个组件,则可以使用 SX 属性。但是,我正在努力为多个组件使用相同的类。在 v4 中,我的代码如下所示:

export const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      padding: theme.spacing(1),
      margin: 'auto',
    },
  })
)
Run Code Online (Sandbox Code Playgroud)

我可以在任何组件中导入这个useStyles钩子并像这样使用它:

const classes = useStyles()
...
<div className={classes.root}>...</div>
Run Code Online (Sandbox Code Playgroud)

该文档说,我可以“用类名覆盖样式”,但他们没有告诉如何做到这一点: https://mui.com/customization/how-to-customize/#overriding-styles-with-class -名称

我是否必须将这些样式放入外部 CSS 文件中?

.Button {
  color: black;
}
Run Code Online (Sandbox Code Playgroud)

我宁愿在我的 ts 文件中定义样式。

我还找到了这个迁移指南: https ://next.material-ui.com/guides/migration-v4/#migrate-makestyles-to-emotion

我不喜欢方法一,因为使用这个 Root 包装器,有条件地应用类很不方便。(特别是对于打字稿,有一些开销)方法二带有外部依赖项和一些样板代码。

理想情况下,我会使用这样的样式,也许在样式对象周围使用一个说唱歌手函数:

export const root = {
  padding: theme.spacing(1),
  margin: 'auto',
}

<div className={root}>...</div>
Run Code Online (Sandbox Code Playgroud)

当然,最后一种方法不起作用,因为 className 需要一个字符串作为输入。有人知道有很少样板代码的替代方案吗?

Mat*_*ong 15

我建议您查看情感的文档以了解详细信息。这个sx道具实际上是传递给情感的。

你可以这样做:

const sx = {
  "& .MuiDrawer-paper": {
    width: drawerWidth
  }
};
<Drawer sx={sx}/>
Run Code Online (Sandbox Code Playgroud)

相当于 MUI v4

const useStyles = makeStyles({
  drawerPaper: {
    width: drawerWidth,
  }
});

const classes = useStyles();

<Drawer
  classes={{
    paper: classes.drawerPaper,
  }}
/>
Run Code Online (Sandbox Code Playgroud)


Onz*_*nza 7

回答你的确切问题,有一些用例(我认为你的不是其中之一,你应该使用样式组件),但是对于像我这样偶然发现它并想要“这个问题的确切答案”而不是“这样做”的人来说相反”,这就是您检索类名的方法。

到目前为止,这还没有记录。

对于使用情感的功能组件,这里有一个用例,其中您有一个第三方组件,该组件需要的不是一个而是多个类名,或者 className 属性不是您应该传递该属性的位置。

import { css, Theme, useTheme } from "@mui/material/styles";
import { css as emotionCss } from "@emotion/css";

const myStyles = {
  basicClass: {
    marginLeft: "1rem",
    marginRight: "1rem",
    paddingLeft: "1rem",
    paddingRight: "1rem",
  },
  optionClass: (theme: Theme) => ({
    [theme.breakpoints.down(theme.breakpoints.values.md)]: {
      display: "none",
    }
  })
}

function MyComponent() {
  cons theme = useTheme();

  // first we need to convert to something emotion can understand
  const basicClass = css(myStyles.basicClass);
  const optionClass = css(myStyles.optionClass(theme));

  // now we can pass to emotion
  const basicClassName = emotionCss(basicClass.styles);
  const optionClassName = emotionCss(optionClass.styles);

  return (
    <ThirdPartyComponent basicClassName={basicClassName} optionClassName={optionClassName} />
  )
}
Run Code Online (Sandbox Code Playgroud)

当您有一个类组件时,如果您使用主题,则需要使用未记录的withTheme组件并包装您的类。@mui/material/styles

当它不是一个用例时

  1. 当您的组件使用单个 className 属性时,只需使用样式组件。
import { styled } from "@mui/material/styles";

const ThrirdPartyStyled = styled(ThirdPartyComponent)(({theme}) => ({
  color: theme.palette.success.contrastText
}))
Run Code Online (Sandbox Code Playgroud)
  1. 即使你有动态风格
import { styled } from "@mui/material/styles";

interface IThrirdPartyStyledExtraProps {
  fullWidth?: boolean;
}

const ThrirdPartyStyled = styled(ThirdPartyComponent, {
  shouldForwardProp: (prop) => prop !== "fullWidth"
})<IThrirdPartyStyledExtraProps>(({theme, fullWidth}) => ({
  color: theme.palette.success.contrastText,
  width: fullWidth ? "100%" : "auto",
}))
Run Code Online (Sandbox Code Playgroud)

即使每个颜色都有某种形式的自定义颜色,您也只需在新的 ThrirdPartyStyled 上使用“sx”即可。

  1. 当您只是尝试重用(您的用例)周围的样式时
import { styled } from "@mui/material/styles";

const ThrirdPartyStyled = styled(ThirdPartyComponent)(({theme}) => ({
  color: theme.palette.success.contrastText
}))
Run Code Online (Sandbox Code Playgroud)

现在,“大概”很酷的是,你的样式现在只是一个对象,你可以导入它并在任何地方使用它,而无需 makeStyles 或 withStyles,据说是一个优势,即使说实话,我从未使用过它周围的出口/进口;不过,代码看起来更干净一些。

您似乎想使用它,所以您所做的就是。

export const myStyles {
  // your styles here
}
Run Code Online (Sandbox Code Playgroud)

因为这个对象在内存中是等价的,并且它总是同一个对象,更容易搞乱样式,理论上它应该和你的钩子一样有效甚至更有效(如果它经常重新渲染,即使设置可能会发生)更长),它将相同的函数存储在内存中,但每次都返回一个新对象。

现在,您可以在您认为合理的任何地方使用这些 myStyles,无论是使用样式组件还是通过分配给 sx。

您可以进一步优化,比如说,如果您始终使用以相同方式设置样式的 div,那么样式化组件MyStyledDiv应该更快,因为它是相同的并且每次都会完成。这要快多少?根据一些消息来源,速度快了 55%,对我来说,重构需要 4 周的时间,而且 JSS 与情感的兼容性很差,所有与 SSR 的混合都会使一切变得无法使用、缓慢且损坏,所以让我们看看到那时整体重构的时间。