用prop覆盖React Component基本样式

时间:2019-07-30 09:25:20

标签: reactjs react-native components theming

我有以下函数,这些函数以通过props传递的自定义值覆盖组件的基本样式:

function overrideCardContainerStyles (props) {
  const {
    width,
    height,
    borderRadius,
    backgroundColor,
    paddingVertical,
    paddingHorizontal,
  } = styles.cardContainer;

  const {
    cardWidth,
    cardHeight,
    cardBorderRadius,
    cardBackgroundColor,
    cardPaddingVertical,
    cardPaddingHorizontal,
  } = props;

  return { 
    width: cardWidth || width,
    height: cardHeight || height,
    borderRadius: cardBorderRadius || borderRadius,
    backgroundColor: cardBackgroundColor || backgroundColor,
    paddingVertical: cardPaddingVertical || paddingVertical,
    paddingHorizontal: cardPaddingHorizontal || paddingHorizontal,
  };
};

尽管该策略可行并且适合于覆盖几种样式,但是随着项目的发展,它将不再有效。我预见到,项目中几乎所有定义的基本样式都将具有被prop覆盖的选项。

是否有更好的方法可以在更优雅,更可扩展的庄园中实现这一目标?

4 个答案:

答案 0 :(得分:1)

您可以使用loadash merge。只需将传递的道具合并到您的样式道具中即可,以便在未定义的情况下使用后备广告。希望这会有所帮助。

答案 1 :(得分:1)

我建议使用相同的命名系统命名样式,并将其属性传递到单个属性中。

例如:

function overrideCardContainerStyles (props) {
  const {
    width,
    height,
    borderRadius,
    backgroundColor,
    paddingVertical,
    paddingHorizontal,
    ...props.styles,
  } = styles.cardContainer;

  return { 
    width,
    height,
    borderRadius,
    backgroundColor,
    paddingVertical,
    paddingHorizontal,
  };
};

我这样做:

const Box = ({ styles }) => (
  <div style={{ color: 'red', ...styles }}>
    Color Text
  </div>
);

const Card = () => (
  <Box styles={{ color: 'green' }} />
);

答案 2 :(得分:0)

我建议使用样式化系统库,您可以将其与样式化组件或Emotion一起使用:

以这种方式创建组件:

import styled from 'styled-components'
import { color } from 'styled-system'

const Box = styled.div`
  ${color}
`

export default Box

color函数将颜色道具colorbg添加到您的组件中:

<Box color="black" bg="blue">
  Blue Box
</Box>

同样,space函数将为您提供边距和填充道具:

import styled from 'styled-components'
import { space } from 'styled-system'

const Box = styled.div`
  ${space}
`

export default Box
<Box ml={3} p={3}>
  Box with spacing
</Box>

ml代表marginLeft,p代表填充。

还有其他一些功能,例如layout用于处理宽度和高度,“边框” ...

它还具有强大的功能,例如主题化和响应性道具。

(示例取自https://styled-system.com/getting-started/

答案 3 :(得分:0)

我有一个不同的解决方案-请注意,这仅适用于material-ui组件(据我所知)。

const useStyles = makeStyles(theme => ({
  card: {
    backgroundColor: "inherit",
    borderRadius: "0px",
    boxShadow: "none"
  }
}));

export const MyCard = props => {
  const classes = useStyles();

  return (
    <Card style={props.style} className={classes.card}>
      <CardContent>
        {props.label}
      </CardContent>
    </Card>
  );
};

在我的主要组件中,我是这样称呼的:

<MyCard
    style={{ width: "125%", color: "red" }}
    label={"This is my card"}
/>

Material-UI将优先于样式道具,而不是其className道具,因此您可以传入自定义样式。