繁体   English   中英

reactjs&mui - 如何正确共享样式?

[英]reactjs&mui - how to properly share styles?

我想在我的整个 web 应用程序之间共享样式。

我的问题:我目前正在使用makeStyles如下所示:

组件_A.js

const useStyles = makeStyles({
    specific_style: {
        padding: '24px',
        // etc.
    }
})

function foo() {

    const classes = useStyles();

    return (
        <div className={classes.specific_style}>This is a styled div</div>
    )
}

组件_B.js

const useStyles = makeStyles({
    specific_style: {
        padding: '24px',
        // etc.
    }
})

function bar() {

    const classes = useStyles();

    return (
        <div className={classes.specific_style}>This is another styled div</div>
    )
}

因此,我目前有很多重复的代码。 我想过把这些类放到一个主题中并像{theme.specific_style}一样访问它,这可能吗? 我试过了,但到目前为止没有成功。

有人可以与我和后面的人分享一个工作示例吗? :)

我想到的可能解决方案:

  • 我知道使用本机 CSS 是可能的,但这对我来说并不合适。
  • 也可以简单地将样式类放入它自己的.js然后导入它,但感觉也不对,因为我已经访问了主题 - 我想这就是这些样式应该存在的地方。

将主题与makeStyles()是在整个文件系统中共享样式的一种方式。 makeStyles()函数除了接受一个对象之外,还可以接受一个函数:

const useStyles = makeStyles((theme) => {
    root: {
        minWidth: '100%',
        color: theme.textColor,
    }
}

通过这种方式,您可以在样式对象中使用更高级别的主题组件。 您需要做的是创建一些主题文件,在其中保留所有共享样式,然后以与导入组件相同的方式导入该对象。

import { lightTheme } from './theme';

其他选项包括使用主题提供程序: https : //material-ui.com/styles/advanced/

您也可以将主题传递给道具。

TL;DR:根据您的讨论,您希望在将样式传递给主题提供程序之前制作样式:

const useStyles = makeStyles({specific_style: {spacing: 8}, /*more */});
function UseTheme() {
  const classes = useStyles();
  return (<ThemeProvider theme={classes}><DeepChild /></ThemeProvider>);
}
function DeepChild() {
  const theme = useTheme();
  return <span className={theme.specific_style}>specific_style spacing</span>;
}

否则,您传递的是原始对象而不是 CSS 类名。 在这个pastebin 中尝试你的风格。

NL;PR:现在,就样式共享原理而言,由于主题提供者在内部是上下文提供者,因此会降低组件的可重用性

有四种样式范围:

  1. 全局样式覆盖:您提到它是常见的 CSS 文件,可以在制作样式时使用前缀“@global”来实现。 我同意你的看法,而不是这里的方式。 当库或组件不公开其类名或通过直接 CSS 覆盖来实现时,它很有用。
const useStyles = makeStyles(
 {'@global': {'.aGlobalStyleClass': {spacing:8} /*more */}
);
function UseTheme() {
  const classes = useStyles();
  return (<div className="aGlobalStyleClass">);
}
  1. 全局样式组件覆盖:创建主题时 这将影响 MUI 组件的所有实例。
//from MUI's page
const theme = createMuiTheme({
  components: {
    // Style sheet name ⚛️
    MuiButton: {
      styleOverrides: {
        // Name of the rule
        textPrimary: {
          // Some CSS
          color: 'white',
        },
      },
    },
  },
});
  1. Contextual Style 组件覆盖:这是您一直在讨论的一个,您可以在其中决定是否覆盖组件初始样式,但是,该组件需要是主题提供者的使用者。 “谨慎应用”,也许将 useStyles() 移动到组件的公共父级是更好的解决方案。 主要示例使用它。

  2. 本地样式组件覆盖:您的公共类名={classes.style} 或 style={}。 如前所述,调用 useStyles() 的地方有很大的不同。 通过在组件层次结构中向上移动样式创建来减少样式重复。

const useStyles = makeStyles({specific_style: {spacing: 8}, /*more */});
function Parent() {
  const classes = useStyles();
  return (<><Child1 classes={classes}/><Child2 classes={classes}/></>);
}
function Child1({classes}) {
  return <span className={classes.specific_style}>specific_style spacing</span>;
function Child2({classes}) {
  return <div className={classes.specific_style}>specific_style spacing</div>;
}

我假设您在上下文和本地样式覆盖之间左右为难。 两者都需要,但我将通过沿组合层次结构扩展样式来消除任何重复的样式,因为主题提供程序的更改将影响其所有组件子树。

如果您计划创建自定义实用程序类并在任何地方使用它们,您可以使用类名将它们添加到组件中的主题覆盖和访问中。

将覆盖添加到 mui 主题

 let theme = createMuiTheme({
      overrides: {
        MuiAppBar: {
          root: {
            transform: 'translateZ(0)'
          }
        }
      },
      props: {
        MuiIconButton: {
          disableRipple: true
        }
      }
    });

    theme = responsiveFontSizes(theme);

    theme.overrides.MuiCssBaseline = {
      '@global': {
        '.testMe': {
          color: 'red'
        },
        '.container-std': {
          [theme.breakpoints.up('lg')]: {
            maxWidth: '1200px',
            marginLeft: 'auto',
            marginRight: 'auto'
          }
        },
        '.container-wide': {
          margin: theme.spacing(2, 2)
        }
      }
    };

注入您的布局

import { theme } from './styles';
import Footer from '../footer/Footer';

export default function Layout(props) {
  const { children } = props;

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Grid container direction="column">
        <Grid item style={{ height: '70px' }}>
          <Header />
        </Grid>
        <Grid item>
          <div>
            {children}
          </div>
        </Grid>
        <Grid item>
          <Footer />
        </Grid>
      </Grid>
    </ThemeProvider>
  );
}

在你的组件中使用它们

export default function HomePage() {
  const classes = useStyles();

  return (
    <Box className={`${classes.hero} container-wide`}>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM