首页 > 解决方案 > JSS 中的 MUI 全局类名称有多可靠?

问题描述

我有这样的代码:

const formControlStyles = {
  root: {
    '&:hover .MuiFormLabel-root': {

     }
  }
}

在主题覆盖中使用类名来访问其他组件是否安全?此外,是否有一种 JSS 方法可以从其他组件中嵌套样式?

标签: javascriptreactjsmaterial-uijss

解决方案


v5 的更新 此答案最初是针对 Material-UI 的 v4 编写的。在 v5 中,Material-UI 不再使用全局类名来应用默认样式——用于默认样式的类具有由 Emotion 生成的类名。全局类名仍然适用,但它们不再受嵌套主题的影响,因此在 v5 中,利用全局类名进行覆盖是完全安全的,而无需使用[class*=...下面我原始答案中提到的语法。


使用全局类名是相当安全的,但有一个警告(在 v4 中)。如果您利用嵌套主题,则在嵌套主题中应用的全局类名将具有不可预测的后缀(例如MuiFormLabel-root-371)。这个后缀是必要的,因为与嵌套主题关联的默认样式可能不同。

为了以完全安全的方式定位类名,您可以使用*= 属性选择器(例如[class*="MuiFormLabel-root"])来检查元素是否具有包含 MuiFormLabel-root而不需要完全匹配的类名。您可以在此处查看Material-UI 本身使用的这种方法。

只要您不打算使用嵌套主题,使用精确匹配全局类名的更简单语法是安全的(并且更具可读性)。另一种方法是在嵌套组件上指定一个 JSS 类,并使用 JSS 语法来引用该类以引用同一样式表中的另一个规则(例如$myFormLabel在我的示例中),但这需要能够应用该类(例如classes.myFormLabel在我的例子)到嵌套组件。

下面是一个示例,它演示了使用嵌套主题时的问题(以及一些可能的解决方案)。

import React from "react";
import {
  ThemeProvider,
  createMuiTheme,
  makeStyles
} from "@material-ui/core/styles";
import FormLabel from "@material-ui/core/FormLabel";

const theme1 = createMuiTheme();
const theme2 = createMuiTheme({
  overrides: {
    MuiFormLabel: {
      root: {
        color: "#00ff00"
      }
    }
  }
});

const useStyles = makeStyles({
  mostlySafe: {
    "&:hover .MuiFormLabel-root": {
      color: "red"
    }
  },
  safeButTediousAndMoreErrorProneSyntax: {
    '&:hover [class*="MuiFormLabel-root"]': {
      color: "purple"
    }
  },
  alternativeApproach: {
    "&:hover $myFormLabel": {
      color: "blue"
    }
  },
  myFormLabel: {}
});
export default function App() {
  const classes = useStyles();
  return (
    <ThemeProvider theme={theme1}>
      <div>
        <div className={classes.mostlySafe}>
          <FormLabel>FormLabel within top-level theme</FormLabel>
        </div>
        <ThemeProvider theme={theme2}>
          <div className={classes.mostlySafe}>
            <FormLabel>
              FormLabel within nested theme (hover styling doesn't work)
            </FormLabel>
          </div>
          <div className={classes.safeButTediousAndMoreErrorProneSyntax}>
            <FormLabel>
              FormLabel within nested theme using safe approach
            </FormLabel>
          </div>
          <div className={classes.alternativeApproach}>
            <FormLabel className={classes.myFormLabel}>
              FormLabel within nested theme without using global class names
            </FormLabel>
          </div>
        </ThemeProvider>
      </div>
    </ThemeProvider>
  );
}

编辑全局类名


推荐阅读