reactjs и mui — как правильно обмениваться стилями?

#javascript #reactjs #material-ui #jsx

#javascript #reactjs #материал-пользовательский интерфейс #jsx

Вопрос:

Я хотел бы поделиться стилями между всем моим веб-приложением.

Моя проблема: makeStyles в настоящее время я использую вот так:

component_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>
    )
}
 

component_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, но мне это кажется неправильным.
  • Также можно было бы просто поместить класс style в свой собственный .js и импортировать его затем, но это тоже не кажется правильным, поскольку у меня уже есть доступ к теме — и я думаю, что именно здесь должны жить такие стили.

Ответ №1:

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. Переопределение компонента контекстного стиля: это тот, который вы обсуждали, где вы решаете, следует ли переопределять начальный стиль компонента, однако компонент должен быть потребителем поставщика темы. «Применяйте это экономно», возможно, лучшим решением будет переместить ваши 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>;
}
 

Я предполагаю, что вы разрываетесь между переопределениями контекстного и локального стилей. Необходимо и то, и другое, но я удалю любой повторяющийся стиль, увеличив масштаб стилей по иерархии композиции, поскольку изменение поставщика темы повлияет на все его компонентное поддерево.

Комментарии:

1. Спасибо за исчерпывающий ответ! Не могли бы вы добавить пример для переопределения глобального стиля? Как именно вы бы создали тему, например, с пользовательской палитрой И глобально измененным, например, стилем карты?

2. Я обновил ответ с помощью переопределения глобального стиля, больше информации здесь , и именно то, что вы спрашивали о палитре, можно найти здесь

3. Большое спасибо за обновление и ссылки тоже!

Ответ №2:

Использование темы с makeStyles() помощью — это один из способов совместного использования стилей во всей вашей файловой системе. makeStyles() Функция может принимать функцию в дополнение к принятию объекта:

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

Таким образом, вы можете использовать компоненты темы более высокого уровня в своих объектах стилей. Что вам нужно будет сделать, это создать некоторый файл темы, в котором вы сохраните все свои общие стили, а затем импортировать этот объект таким же образом, как вы импортировали бы компонент.

 import { lightTheme } from './theme';
 

Другие варианты включают использование поставщика темы: https://material-ui.com/styles/advanced /

Также вы могли бы передать теме реквизит.

Комментарии:

1. Я бы предпочел способ тематизации, я уже пробовал, как описано здесь: material-ui.com/styles/advanced Дело в том, что я не знаю, как использовать весь класс, который я определил в теме. Я думал, что это будет похоже className={theme.specific_style} , но таким образом мой браузер просто сообщает мне, что я использую объект в качестве класса. Похоже, класс не переведен в CSS. Не могли бы вы привести пример определения некоторых стилей css в классе и использовать его затем, определив className?

Ответ №3:

Если вы планируете создавать пользовательские служебные классы и использовать их где угодно, вы можете добавить их в переопределение темы и получить доступ к своим компонентам, используя имена классов.

Добавьте переопределения в тему 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`}>