【问题标题】:How reliable are MUI Global Class names in JSS?JSS 中的 MUI 全局类名称有多可靠?
【发布时间】:2020-06-28 11:19:15
【问题描述】:

我有这样的代码:

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

     }
  }
}

在主题覆盖中使用类名访问其他组件是否安全?另外,有没有 JSS 方式从其他组件中嵌套样式?

【问题讨论】:

    标签: javascript reactjs material-ui jss


    【解决方案1】:

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


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

    为了以完全安全的方式定位类名,您可以使用*= attribute selector(例如[class*="MuiFormLabel-root"])检查元素是否具有包含的类名strong> MuiFormLabel-root 而不需要完全匹配。您可以在 Material-UI 本身中看到这种方法here

    只要您不打算使用嵌套主题,使用更简单的语法来精确匹配全局类名是安全的(并且更具可读性)。另一种方法是在嵌套组件上指定一个 JSS 类,并使用 referring to another rule in the same stylesheet 的 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>
      );
    }
    

    【讨论】:

    • 感谢您的帮助!在您回答后一直困扰着我的一个问题(特别是 MUI 的 AutoComplete 组件实现)。如果disableGlobal 设置为true 会发生什么?自动完成组件会中断吗?样式会无法访问吗?
    • @Gasim 这是一个有趣的观点。是的,如果 disableGlobal 设置为 true,那将破坏 Autocomplete 样式。在 v5 中,计划将 JSS 替换为 styled-components 作为内部使用的样式解决方案。我还不知道这会带来什么影响,但我怀疑 MUI 将变得更多依赖于全局类名,而不是更少。我怀疑disableGlobal 的选项将完全消失。
    • @Gasim FYI -- 这是disableGlobal 发挥作用的代码参考:github.com/mui-org/material-ui/blob/v4.9.5/packages/…
    猜你喜欢
    • 2023-03-16
    • 2018-11-05
    • 2020-07-11
    • 2016-08-20
    • 2013-10-12
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多