【问题标题】:Using props to set '&:hover' background-color使用 props 设置 '&:hover' 背景色
【发布时间】:2019-07-27 05:54:00
【问题描述】:

我正在包装 MUI 的 Chip 组件,以便我可以为 colors 属性传递除“主要”和“次要”之外的值。如果芯片是可点击的,我还想保持悬停效果,以便当光标悬停在芯片上时,芯片会转换为不同的颜色。颜色作为道具传入,因此设置backgroundColorcolor 很容易:

<Chip
  style={{
    backgroundColor: props.backgroundColor,
    color: props.color
  }}
/> 

但是,由于我还想将悬停颜色作为道具传递,我需要执行以下操作:

<Chip
  style={{
    backgroundColor: props.backgroundColor,
    color: props.color,
    '&:hover': {
      backgroundColor: props.hoverBackgroundColor,
      color: props.hoverColor
    }
  }}
/> 

但是,&amp;:hover(据我所知)不能在 style 属性内使用。通常,&amp;:hover 将在传递给withStyles 的样式对象内使用,但我无法从那里访问道具。有什么建议吗?

【问题讨论】:

    标签: css reactjs material-ui jsx


    【解决方案1】:

    MUI v5中,您可以使用sx prop 来设置:hover 等伪类的样式:

    <Chip
      label="Chip"
      onClick={() => {}}
      sx={{
        ':hover': {
          bgcolor: 'red',
        },
      }}
    />
    

    如果你想创建一个可重用的样式组件,另一种选择是styled()

    const options = {
      shouldForwardProp: (prop) => prop !== 'hoverBgColor',
    };
    const StyledChip = styled(
      Chip,
      options,
    )(({ hoverBgColor }) => ({
      ':hover': {
        backgroundColor: hoverBgColor,
      },
    }));
    
    <StyledChip label="Chip" onClick={() => {}} hoverBgColor="red" />
    

    【讨论】:

      【解决方案2】:

      您可以通过创建自己的自定义芯片组件来实现这一点。为了能够使用道具来控制样式,可以使用makeStylesmakeStyles 函数返回一个钩子,该钩子可以接受一个对象参数,以便为您的样式提供变量。

      这是一个可能的 CustomChip 实现:

      import React from "react";
      import Chip from "@material-ui/core/Chip";
      import { makeStyles } from "@material-ui/core/styles";
      import { emphasize } from "@material-ui/core/styles/colorManipulator";
      
      const useChipStyles = makeStyles({
        chip: {
          color: ({ color }) => color,
          backgroundColor: ({ backgroundColor }) => backgroundColor,
          "&:hover, &:focus": {
            backgroundColor: ({ hoverBackgroundColor, backgroundColor }) =>
              hoverBackgroundColor
                ? hoverBackgroundColor
                : emphasize(backgroundColor, 0.08)
          },
          "&:active": {
            backgroundColor: ({ hoverBackgroundColor, backgroundColor }) =>
              emphasize(
                hoverBackgroundColor ? hoverBackgroundColor : backgroundColor,
                0.12
              )
          }
        }
      });
      const CustomChip = ({
        color,
        backgroundColor,
        hoverBackgroundColor,
        ...rest
      }) => {
        const classes = useChipStyles({
          color,
          backgroundColor,
          hoverBackgroundColor
        });
        return <Chip className={classes.chip} {...rest} />;
      };
      export default CustomChip;
      

      样式方法(包括使用emphasize 函数生成悬停颜色和活动颜色)基于Chip 内部使用的方法。

      然后可以这样使用:

            <CustomChip
              label="Custom Chip 1"
              color="green"
              backgroundColor="#ccf"
              onClick={() => {
                console.log("clicked 1");
              }}
            />
            <CustomChip
              label="Custom Chip 2"
              color="#f0f"
              backgroundColor="#fcc"
              hoverBackgroundColor="#afa"
              onClick={() => {
                console.log("clicked 2");
              }}
            />
      

      这是一个演示这个的 CodeSandbox:


      这是该示例的 Material-UI v5 版本:

      import Chip from "@material-ui/core/Chip";
      import { styled } from "@material-ui/core/styles";
      import { emphasize } from "@material-ui/core/styles";
      import { shouldForwardProp } from "@material-ui/system";
      function customShouldForwardProp(prop) {
        return (
          prop !== "color" &&
          prop !== "backgroundColor" &&
          prop !== "hoverBackgroundColor" &&
          shouldForwardProp(prop)
        );
      }
      const CustomChip = styled(Chip, { shouldForwardProp: customShouldForwardProp })(
        ({ color, backgroundColor, hoverBackgroundColor }) => ({
          color: color,
          backgroundColor: backgroundColor,
          "&:hover, &:focus": {
            backgroundColor: hoverBackgroundColor
              ? hoverBackgroundColor
              : emphasize(backgroundColor, 0.08)
          },
          "&:active": {
            backgroundColor: emphasize(
              hoverBackgroundColor ? hoverBackgroundColor : backgroundColor,
              0.12
            )
          }
        })
      );
      
      export default CustomChip;
      

      【讨论】:

      • 这似乎工作得很好。不幸的是,我使用的是不支持钩子的 React 版本。希望我们能很快到达那里。同时,我想出了一个解决方案,它使用 HOC 将使用 props 的样式注入到组件中。这是CodeSandbox
      • Material-UI v4 将需要 hooks 支持,因此为了不断获得 Material-UI 的进一步增强,您肯定希望升级 React。只要您已经在使用 React 16 而不是某个早期版本,它应该是一个非常轻松的升级。
      • @RyanCogswell 为什么又从系统包中调用shouldForwardPropdocs 中的示例没有做到这一点,无论是否在第二个 shouldForwardProp 的情况下在代码盒中玩耍时,它对我没有任何影响。
      • @NearHuscarl 我想我包含了它,因为在查看源代码时,当您指定自定义 shouldForwardProp 时,它不会添加到默认值 - 它会替换它。假设默认实现至少在某些情况下会产生影响,我将其包括在内,但我还没有发现它似乎会产生影响的情况。文档中的示例确实包含默认实现的一部分(检查sx),但我不清楚在什么情况下会产生影响。
      • it isn't additive to the default 这就是为什么它让我感到困惑,看起来你的代码是基于源代码的方式,因为自定义shouldForwardProp overrides the original one from the system completely,它不使用createChainedFunction合并多个功能。在阅读源代码时,我可能在某处错过了一些额外的魔法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 2013-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多