类型为特异性选择器所需的CSS空定义(React中的材料UI)

时间:2019-07-11 08:05:52

标签: reactjs typescript material-ui

未选择的切换按钮的样式效果很好。

但是当您没有定义空的类选择器时,所选切换按钮的样式不会出现:

./ App.js

import * as React from "react";
import { render } from "react-dom";

import { createStyles, WithStyles } from "@material-ui/core";
import { ToggleButtonGroup, ToggleButton } from "@material-ui/lab";
import { withStyles } from "@material-ui/core/styles";

const styles = () =>
  createStyles({
    root: {
      backgroundColor: "blue",
      "&$selected": {
        color: "blue",
        backgroundColor: "yellow"
      }
    },
    // this empty definition needs to be here otherwise it won't work
    selected: {}
  });

export interface IAppProps extends WithStyles<typeof styles> {}

const App: React.FC<IAppProps> = ({ classes }: IAppProps) => {
  return (
        <ToggleButton
          classes={{
            root: classes.root,
            selected: classes.selected
          }}
          selected={true}
        >
          option 1
        </ToggleButton>
  );
};

const AppWithStyles = withStyles(styles)(App);
const rootElement = document.getElementById("root");
render(<AppWithStyles />, rootElement);

也许与道具中的类型定义有关。当从 styles 定义中删除“ selected”选择器时,它在IAppProps接口中不再可用。

如何在界面中定义此类型?

工作示例:https://codesandbox.io/s/elated-sammet-y7wh7?fontsize=14


更新1:还尝试按照描述in the material-ui docs

增强道具
const styles = () =>
  createStyles({
    toggleButton: {
      backgroundColor: "blue",
      "&$toggleButtonSelected": {
        color: "blue",
        backgroundColor: "yellow"
      }
    },
  });

export interface IAppProps {
  classes: {
    toggleButton: string;
    toggleButtonSelected: string;
  };
}

const App: React.FC<IAppProps> = ({ classes }: IAppProps) => {
// ...

没有运气。


更新2:使用钩子可以强制类型转换为多余,但也无法解决此问题:

import * as React from "react";
import { render } from "react-dom";

import { createStyles, makeStyles } from "@material-ui/core";
import { ToggleButtonGroup, ToggleButton } from "@material-ui/lab";

const useStyles = makeStyles(() =>
    createStyles({
      root: {
        backgroundColor: "blue",
        "&$selected": {
          color: "blue",
          backgroundColor: "red"
        }
      },
      // this still needs to be there...
      // selected: {}
    })
  )

export interface IAppProps {}

const App: React.FC<IAppProps> = () => {

  const classes = useStyles();

  return ( 
    // ...
  )
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);

1 个答案:

答案 0 :(得分:1)

我相信您对JSS的工作原理和某些语法的含义有误解。相关文档为here

当定义样式对象(或接受主题并返回对象的函数)时,JSS将该对象中的每个键称为“规则”。关键是规则名称,JSS会将值转换为CSS类。从classes返回的useStyles对象,或者在使用withStyles时作为道具注入的$ruleName对象,然后将规则名称映射到生成的CSS类名称。

&语法是一种引用样式对象中其他规则之一的CSS类名称的方法。 root引用父规则。在您的示例中,您有名为selectedroot: { backgroundColor: "blue", "&$selected": { color: "blue", backgroundColor: "red" } }, selected: {} 的规则(未注释时)。

以下内容:

.root-0 {
   background-color: blue;
}
.root-0.selected-0 {
   color: blue;
   background-color: red;
}

将像以下那样编译为CSS:

          classes={{
            root: classes.root,
            selected: classes.selected
          }}
          selected={true}

通过将以下内容传递给Material-UI:

selected: {}

您告诉它除了用于默认样式的类名之外,还将“ root-0 selected-0”用作类名。如果没有空的$selected规则名称,就不能从root规则中引用selected(如果这样做,JSS应该在控制台中向您发出警告)。

有一个稍微简单的替代方法(从v4开始),用于引用selected类名。 Mui-selected是Material-UI特殊状态之一,它称为pseudo-classes,并且文档提供了每种的默认类名称(例如root: { backgroundColor: "blue", "&.Mui-selected": { color: "blue", backgroundColor: "red" } } )。

这意味着您可以执行以下操作:

selected: {}

这不再引用其他规则,因此selected: classes.selected道具中不需要classes,也不需要selected={true}。相反,这是指rotation时Material-UI应用于默认样式的实际类名。