【问题标题】:How to get property based CSS styles to work with local rule references in Material-UI and JSS?如何让基于属性的 CSS 样式与 Material-UI 和 JSS 中的本地规则引用一起使用?
【发布时间】:2021-03-04 09:27:44
【问题描述】:

我找不到让local rule reference(在下面的代码中命名为'& $value')与using functions for CSS definitions 一起完全工作的方法。使用接受 StyleProperties 对象并返回 CSS 值的函数定义的任何 CSS 属性在为引用其他本地规则的规则定义时将被简单地忽略;请看代码和cmets:

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'&amp; $value' 规则级别而不是在 CSS 属性级别使用接受我的 StyleProperties 对象的函数,但是这两种方法都完全忽略了在 '&amp; $value' 中找到的所有 CSS 定义。

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

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

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

【问题讨论】:

标签: reactjs material-ui jss


【解决方案1】:

问题是您正在从CellValue 调用useStyles。这会导致为value 规则生成两个不同的类,并为static 规则生成两个不同的类。为Cell 生成的value 类在应用于staticstatic 类中被"&amp; $value" 引用,但为Value 生成的value 类应用于Value元素,因此它不会被 static 类中的后代选择器匹配。

您可以通过仅在一处调用 useStyles 并将 value 类名向下传递给 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>
  );
}

【讨论】:

  • 这是有道理的,确实解决了我的问题,谢谢。事实上,一些样式,如颜色和背景颜色,仍然被应用于嵌套在静态单元格中的元素,这让我看不到问题的原因。
  • @nxn 让你失望的行为是由于我没有深入探讨的微妙之处。当您在同一规则中同时拥有静态 CSS 属性和动态(即基于 prop)的 CSS 属性时,JSS 实际上会创建两个单独的类——一个用于静态部分,一个用于动态部分。 Cell 和 Value 共享相同的静态类名,但动态部分最终是特定于元素的。在此处查看控制台日志:codesandbox.io/s/…
猜你喜欢
  • 2019-12-26
  • 1970-01-01
  • 2021-11-18
  • 2021-10-10
  • 2021-04-06
  • 2019-03-16
  • 2020-09-10
  • 2018-01-09
  • 2019-09-01
相关资源
最近更新 更多