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

Posted

技术标签:

【中文标题】使用 props 设置 \'&:hover\' 背景色【英文标题】: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 的样式对象内使用,但我无法从那里访问道具。有什么建议吗?

【问题讨论】:

【参考方案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 为什么又从系统包中调用shouldForwardProp? docs 中的示例没有做到这一点,无论是否在第二个 shouldForwardProp 的情况下在代码盒中玩耍时,它对我没有任何影响。 @NearHuscarl 我想我包含了它,因为在查看源代码时,当您指定自定义 shouldForwardProp 时,它不会添加到默认值 - 它会替换它。假设默认实现至少在某些情况下会产生影响,我将其包括在内,但我还没有发现它似乎会产生影响的情况。文档中的示例确实包含默认实现的一部分(检查sx),但我不清楚在什么情况下会产生影响。 it isn't additive to the default 这就是为什么它让我感到困惑,看起来你的代码是基于源代码的方式,因为自定义shouldForwardProp overrides the original one from the system completely,它不使用createChainedFunction合并多个功能。在阅读源代码时,我可能在某处错过了一些额外的魔法。

以上是关于使用 props 设置 '&:hover' 背景色的主要内容,如果未能解决你的问题,请参考以下文章

为啥 :hover 不适用于 tr 元素?

有没有办法在 html 电子邮件中的“a:hover”上的 href 链接上设置内联样式?

Vue.js + Typescript:如何将@Prop 类型设置为字符串数组?

Cascader 级联选择器hover选择效果

背后的原因 (!nextProps.data.loading && this.props.data.loading)

stylus选中hover元素的兄弟元素下的子元素