Почему вам нужно применить два сгенерированных имени класса (root и отключено) к DOM, чтобы заставить его работать? - PullRequest
1 голос
/ 14 июля 2020

Чтобы настроить компоненты с помощью material-ui, вы можете сделать это:

const styles = {
  root: {
    '&$disabled': {
      color: 'white',
    },
  },
  disabled: {}, // <-- why important?
};

Это компилируется в:

.root-x.disable-x {
  color: white;
}

Но тогда документация говорит :

⚠️ Вам нужно применить два сгенерированных имени класса (root и отключено) к DOM, чтобы заставить его работать.

Я обнаружил сложную способ, которым это правда. Например, в приведенном ниже фрагменте просто удалите отключенный класс (или удалите отключенный ключ из styles выше), и вы обнаружите, что ваша отключенная кнопка больше не имеет белого текста.

<Button
  disabled
  classes={{
    root: classes.root, // class name, e.g. `root-x`
    disabled: classes.disabled, // <-- why important?
  }}
>

Вы можете попробовать это в этой песочнице: https://codesandbox.io/s/material-demo-hzqwm

Итак, почему вам нужно применить два сгенерированных имени класса (root и отключено) к DOM, чтобы сделать это работать?

Кажется естественным определить отключенный стиль таким образом, но это не приводит к тому, что отключенная кнопка не будет иметь белый текст.

const styles = {
  root: {},
  disabled: {
      color: 'white',
  },
};

Есть ли сценарий, в котором вы бы использовали этот способ установки отключенного стиля?

1 Ответ

1 голос
/ 15 июля 2020

У вас есть несколько разных вопросов.

Вопрос 1: Почему disabled: {} необходим в стилях ниже?

const styles = {
  root: {
    '&$disabled': {
      color: 'white',
    },
  },
  disabled: {}, // <-- why important?
};

Синтаксис $disabled - это механизм для ссылки в другое правило в той же таблице стилей. В терминологии, используемой в JSS, указанный выше блок создает таблицу стилей с двумя правилами: root и disabled. Имя класса CSS будет сгенерировано для каждого из этих правил, а $disabled будет преобразовано в это сгенерированное имя класса. Если вы не укажете disabled: {}, это правило не будет существовать в таблице стилей (поэтому JSS не будет генерировать соответствующее имя класса), а JSS не будет знать, что $disabled должно разрешить, и сообщит вам об этом в консоли. :

Предупреждение: [JSS] Не удалось найти указанное правило «отключено» в «makeStyles».

Вопрос 2: Почему disabled: classes.disabled необходим в опоре classes ниже?

<Button
  disabled
  classes={{
    root: classes.root, // class name, e.g. `root-x`
    disabled: classes.disabled, // <-- why important?
  }}
>

Как вы указали в своем вопросе, стили будут компилироваться примерно так:

.root-x.disable-x {
  color: white;
}

Это будет соответствовать элементу, который имеет как класс root-x, так и класс disable-x в своем имени. Если вы не передадите disabled: classes.disabled классу Button, он не узнает об имени класса disable-x и не будет применен к Button; поэтому он не будет соответствовать правилу CSS, поскольку Button будет иметь только root-x в имени своего класса.

Стили также будут успешно применены , если вы выполните следующее:

<Button disabled className={`${classes.root} ${classes.disabled}`}>

Основное преимущество использования classes состоит в том, что вы всегда можете передавать те же классы, даже если кнопка в данный момент не отключена (например, если disabled находится в состоянии, которое может может быть переключен каким-либо действием), а отключенный класс будет применяться только , когда это необходимо, но в случае, когда disabled===true, className={`${classes.root} ${classes.disabled}`} имеет тот же эффект, что и classes={{ root: classes.root, disabled: classes.disabled }}.

Вопрос 3: Почему я не могу определить отключенный стиль, как показано ниже?

const styles = {
  root: {},
  disabled: {
      color: 'white',
  },
};

Проблема здесь CSS специфичность .

Ниже часть стилей по умолчанию для кнопки :

export const styles = (theme) => ({
  root: {
    color: theme.palette.text.primary,
    '&$disabled': {
      color: theme.palette.action.disabled,
    },
  },

Что касается специфичности, здесь используется один селектор классов для определения цвета по умолчанию. Затем он использует комбинацию двух селекторов классов для определения отключенного цвета - это придает отключенным стилям большую специфичность, чтобы гарантировать, что отключенные стили выиграют, когда кнопка находится в отключенном состоянии. определяется следующим образом:

export const styles = (theme) => ({
  root: {
    color: theme.palette.text.primary,
  },
  disabled: {
    color: theme.palette.action.disabled,
  },

эти два правила будут иметь одинаковую специфичность. В этом случае выигрывает тот, который произойдет последним (в отношении порядка объявлений стилей в элементе <head>). Это будет работать для стилей по умолчанию, но если вы затем решите переопределить цвет по умолчанию (но не отключенный цвет) с чем-то вроде:

const StyledButton = withStyles({
  root: {
    color: 'blue'
  }
})(Button);

Эти стили появятся после стилей по умолчанию в заголовке ( подробнее о том, почему объяснено здесь ), что также означает после отключенных по умолчанию стилей. Тогда, если стили disabled и root имеют одинаковую специфичность, синий цвет будет использоваться, даже когда кнопка была отключена (вместо использования theme.palette.action.disabled). Material-UI постоянно использует повышенную специфичность правил стиля для состояний, отличных от состояния по умолчанию (например, отключено, сфокусировано, ошибка), чтобы гарантировать, что эти стили преобладают над настройками стилей по умолчанию, поэтому вам нужно использовать такую ​​же степень специфичности в ваших переопределениях этих других штатов.

Подразумеваемый вопрос 4: Есть ли более простой способ определить отключенные стили?

Да, вы можете найти в документации здесь имена глобальных классов для «псевдоклассов» . Например, имя класса, используемое для отключенного состояния, всегда Mui-disabled. Это означает, что вы можете создать кнопку с настраиваемым отключенным видом, используя следующее:

const CustomButton = withStyles({
  root: {
    '&.Mui-disabled': {
      color: 'white',
    },
  }
})(Button);

Изменить пользовательскую отключенную кнопку

...