如何在createMuiTheme()中创建CSS类并直接使用它们,而不必从组件“类”道具中获取其值?

时间:2019-01-02 18:45:02

标签: reactjs material-ui

我正在尝试避免输入冗余代码。在多个组件中,我创建了相同的CSS类。我想使用createMuiTheme()将它们添加到主题中,然后仅直接使用主题中的样式,而不必在Component道具上调用“类”道具。

我试图像这样在根组件上创建一个主题:

const theme = createMuiTheme({
  palette:{
      primary: {
        main: '#47286E',
        light: '#D91677'
      },
      secondary: {
        main: '#9156D8' 
      },
  },

 fab: {
    position: "relative",
    top: 0,
    marginTop: 20px
    textTransform: 'none',
    width: 220,
    height: 50
  },

});

然后我将主题传递给使用的其他组件

<MuiThemeProvider theme={theme}>

我尝试将fab按钮直接导入组件内部

<Fab variant="extended" className={this.props.theme.fab} size='small'>
    Change
</Fab>

但是,当我尝试获取fab css类时,我似乎没有任何价值。我只是不想创建一个全新的

const styles = theme => {
    blabbla
}

如果需要的主题已经传递到其子组件,则使用“类”道具将其导入每个组件。

3 个答案:

答案 0 :(得分:2)

我认为createMuiTheme并不是为了这个目的。

或者,您可以只创建要重用的样式对象

const styles = {
  fab: {
    position: "relative",
    top: 0,
    marginTop: 20px
    textTransform: 'none',
    width: 220,
    height: 50
  }
};

只需导入并在需要的地方使用

import fabStyles from '../../somewhere-everyone-can-get-it.js';
import styles from './styles-for-this-component.js';

...

withStyles({...fabStyles, ...styles})(Component);

如果需要主题和样式。

withTheme(withStyles({...fabStyles, ...styles})(Component));

您也可以使用recompose进行清理。

答案 1 :(得分:0)

className={this.props.theme.fab}不起作用,因为this.props.theme.fab是一个对象,而不是类名。使用withStyles时,它会生成一个唯一的类名(例如,可通过props.classes.fab获得),并将该类的CSS注入文档的头部。您主题中的fab对象尚未完成这项工作。

下面的代码显示了避免冗余代码的几种方法。第一个是withFab函数,用于封装CSS和对withStyles的调用。

第二个对象更直接地使用fab对象,只是将其传递给style属性,而不是className属性。您可以从theme.fab(而不是单独的js文件)中获得与您的初始方法类似的样式,但是除非您担心能够通过其他方法覆盖它,否则没有必要将其放在主题中MuiThemeProviders在您的呈现层次结构中。

第二种(样式属性)方法有一些缺点:

  • 如果您在许多不同的元素上使用此功能,则在DOM中每个元素上都多余地指定了CSS。
  • 它不支持需要类的CSS(例如,使用:hover之类的伪元素)

因此,我建议使用与下面显示的第一个选项(UseWithFab/withFab)类似的内容。

withFab.js

import withStyles from "@material-ui/core/styles/withStyles";

const styles = {
  fab: {
    backgroundColor: "lightblue"
  }
};
export const fabStyles = {
  backgroundColor: "lightgreen"
};
const withFab = component => {
  return withStyles(styles)(component);
};
export default withFab;

index.js

import React from "react";
import ReactDOM from "react-dom";
import withFab, { fabStyles } from "./withFab";

const UseWithFab = withFab(props => {
  return <div className={props.classes.fab}>Using withFab</div>;
});
const UseFabStyles = props => {
  return <div style={fabStyles}>Using fabStyles</div>;
};
function App(props) {
  return (
    <>
      <UseWithFab />
      <UseFabStyles />
    </>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit 0xlk0vxmxn

答案 2 :(得分:0)

这些都是很好的答案。我正在做笔记 :) 当我第一次阅读这篇文章时,我怀疑直觉是在使用内置 MUI 主题中的 overrides 键。

我经常发现覆盖键是一种更方便的方式来实现在应用中“更频繁”使用的格式。

这是一个两步过程:

  1. 决定要修改哪个 MUI 组件
  2. 使用适合您的命名约定设置 className 属性
import clsx from 'clsx'; // not required, but handy in the long-run
import Fab from '@material-ui/core/Fab';

const Component = () => {
  ...
  return <Fab className=clsx('MyCustomFab') />
}
// my theme prop for the MUI <ThemeProvider theme={myTheme} />

export default createMuiTheme({
  ...
  overrides: {
    MuiFab: {
      root: {
        '&.MyCustomFab': { // note: the "no-space" => MuiFab AND ...
          backgroundColor: "lightblue",
        }
      }
    }
  }
}