使用 props 设置 '&:hover' 背景色

IT技术 css reactjs material-ui jsx
2021-04-04 20:44:59

我正在包装 MUI 的Chip组件,以便我可以为colorsprop传递除“primary”和“secondary”之外的值如果芯片可点击,我还想保持悬停效果,以便当光标悬停在芯片上时,芯片会转换为不同的颜色。颜色作为props传递,所以很容易设置backgroundColorcolor

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

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

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

但是,&:hover(据我所知)不能在styleprops内部使用通常,&:hover将在传递到 的样式对象内部使用withStyles,但我无法从那里访问props。有什么建议?

2个回答

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

这是一个可能的 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;

编辑芯片颜色

it isn't additive to the default这就是为什么它让我感到困惑,看起来您的代码是基于源代码的方式,因为自定义完全shouldForwardProp 覆盖了系统中的原始代码,它不createChainedFunction用于合并多个功能。在阅读源代码时,我可能会在某处错过一些额外的魔法。
2021-05-24 20:44:59
这似乎工作得很好。不幸的是,我使用的是不支持钩子的 React 版本。希望我们能很快到达那里。与此同时,我想出了一个解决方案,它使用 HOC 将使用 props 的样式注入到组件中。这是CodeSandbox
2021-05-26 20:44:59
@RyanCogswell 为什么您shouldForwardProp再次从系统包中调用文档的示例并没有做到这一点,在带有或不带有第二个shouldForwardProp.
2021-06-03 20:44:59
Material-UI 的 v4 将需要 hooks 支持,因此为了继续获得进一步的 Material-UI 增强功能,您肯定希望升级 React。只要你已经在 React 16 而不是某个早期版本,它应该是一个非常轻松的升级。
2021-06-09 20:44:59
@NearHuscarl 我想我包含了它,因为在查看源时,当您指定一个自定义时shouldForwardProp,它看起来像它不添加到默认值 - 它会替换它。假设默认实现至少对某些场景有影响,我将其包含在内,但我还没有发现它似乎有所作为的场景。文档中的示例确实包括默认实现的一部分(检查sx),但我不清楚在什么情况下会产生影响。
2021-06-14 20:44:59

MUI v5 中,您可以使用sxprop来设置伪类的样式,例如: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" />

代码沙盒演示