如何获得基于 属性 的 CSS 样式以在 Material-UI 和 JSS 中使用本地规则引用?

How to get property based CSS styles to work with local rule references in Material-UI and JSS?

我找不到同时获得两个 local rule reference (named '& $value' in the code below) to fully work in conjunction with using functions for CSS definitions 的方法。任何使用接受 StyleProperties 对象并返回 CSS 值的函数定义的 CSS 属性在为引用其他本地规则的规则定义时将被简单地忽略;请查看代码和评论:

import * as React from "react";

import { Theme, makeStyles, createStyles } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import clsx from "clsx";

type StyleProperties = {
  scale: number;
};

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: (props: StyleProperties) => {
      const size = `${2.0 * props.scale}rem`;

      return {
        position: "relative",
        backgroundColor: theme.palette.background.paper,
        border: `1px solid ${theme.palette.divider}`,
        width: size,
        height: size,
        "& > div": {
          position: "absolute"
        }
      };
    },

    value: {
      color: theme.palette.text.primary,
      width: "100%",
      height: "100%",
      textAlign: "center",
      lineHeight: (props: StyleProperties) => `${2.0 * props.scale}rem`
    },

    static: {
      "& $value": {
        // Following are OK
        color: theme.palette.action.disabled,
        backgroundColor: theme.palette.action.disabledBackground,

        // Ignored
        border: (props: StyleProperties) =>
          `${0.0625 * props.scale}rem solid red`

        // Comment out above line and uncomment the following to see expected output
        // if the value 2.0 was passed in through props.
        //border: `${ 0.0625 * 2.0 }rem solid red`,
      }
    }
  })
);

type ValueProperties = {
  value: string;
  scale: number;
};

function Value(props: ValueProperties) {
  const classes = useStyles(props);
  return <div className={clsx(classes.value)}>{props.value}</div>;
}

type CellProperties = {
  static: boolean;
  scale: number;
};

function Cell(props: CellProperties) {
  const classes = useStyles(props);
  return (
    <div className={clsx(classes.root, { [classes.static]: props.static })}>
      <Value value="value" scale={props.scale} />
    </div>
  );
}

export default function App() {
  return (
    <div className="App">
      <CssBaseline />
      <Cell static={false} scale={2.0} />
      <Cell static={true} scale={2.0} />
    </div>
  );
}

我也尝试过使用函数在 static'& $value' 规则级别而不是 CSS 属性 级别接受我的 StyleProperties 对象, 但两种方法都完全忽略了 '& $value'.

中的所有 CSS 定义

使用上述代码时没有错误消息或警告输出。在搜索 Material-UI 和 JSS 的文档后,我没有发现任何与此场景相关的已知限制的提及。

最终,根据StyleProperties提供的值定义CSS和Material-UI Theme是对接口的严格要求我的应用程序。因此,如果您想建议一种替代方法来声明基于层次结构的样式规则,请记住这一点。

编辑:根据要求,我提供了一个代码沙箱来演示该问题:https://codesandbox.io/s/relaxed-bird-sklgr——参见第 43 行的 border 定义和事实它没有被应用。

问题是您同时从 CellValue 调用 useStyles。这会导致为 value 规则生成两个不同的 classes,并为 static 规则生成两个不同的 classes。为 Cell 生成的 value class 被应用于 Cellstatic class 中的 "& $value" 引用,但它是为 Value 生成的 value class 应用于 Value 元素,因此它与 static [=35 中的后代选择器不匹配=].

您可以通过仅在一处调用 useStyles 并将 value class 名称传递给 Value 元素来解决此问题,如下例所示:

import * as React from "react";

import { Theme, makeStyles, createStyles } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import clsx from "clsx";

type StyleProperties = {
  scale: number;
};

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: (props: StyleProperties) => {
      const size = `${2.0 * props.scale}rem`;

      return {
        position: "relative",
        backgroundColor: theme.palette.background.paper,
        border: `1px solid ${theme.palette.divider}`,
        width: size,
        height: size,
        "& > div": {
          position: "absolute"
        }
      };
    },

    value: {
      color: theme.palette.text.primary,
      width: "100%",
      height: "100%",
      textAlign: "center",
      lineHeight: (props: StyleProperties) => `${2.0 * props.scale}rem`
    },

    static: {
      "& $value": {
        color: theme.palette.action.disabled,
        backgroundColor: theme.palette.action.disabledBackground,

        border: (props: StyleProperties) =>
          `${0.0625 * props.scale}rem solid red`
      }
    }
  })
);

type ValueProperties = {
  value: string;
  scale: number;
  className: string;
};

function Value(props: ValueProperties) {
  return <div className={props.className}>{props.value}</div>;
}

type CellProperties = {
  static: boolean;
  scale: number;
};

function Cell(props: CellProperties) {
  const classes = useStyles(props);
  return (
    <div className={clsx(classes.root, { [classes.static]: props.static })}>
      <Value value="value" className={classes.value} scale={2.0} />
    </div>
  );
}

export default function App() {
  return (
    <div className="App">
      <CssBaseline />
      <Cell static={false} scale={2.0} />
      <Cell static={true} scale={2.0} />
    </div>
  );
}