【问题标题】:Override React Component base styles with props使用 props 覆盖 React 组件的基本样式
【发布时间】:2019-12-07 15:41:59
【问题描述】:

我有以下函数,它使用作为道具传递的自定义值覆盖我的组件基本样式:

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,
  };
};

虽然此策略有效并且适用于覆盖一些样式,但随着项目的发展,它不会有效。我设想项目中几乎所有定义的基本样式都可以选择用道具覆盖。

有没有更好的方法在更优雅和可扩展的庄园中实现这一目标?

【问题讨论】:

  • 为什么不使用 styles 属性并将其合并到样式变量中?
  • 感谢您的回答,因为这为我指明了正确的方向。我使用了扩展扩展运算符并合并了两个对象。最后一块拼图是这篇文章:davidwalsh.name/merge-objects

标签: reactjs react-native components theming


【解决方案1】:

您可以为此使用loadash merge。只需将传递的道具合并到您的样式道具中,这样如果未定义,将使用回退。希望这会有所帮助。

【讨论】:

  • 感谢您的回答,因为它为我指明了正确的方向。我使用扩展运算符将我的基本样式与我的覆盖合并。谢谢
【解决方案2】:

我建议使用相同的命名系统来命名您的样式,并在单个属性中传递它们的属性。

例如:

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' }} />
);

【讨论】:

  • 很好的答案,但我采用了不同的策略:function mergeStyles (base, overrides) { return { ...base, ...overrides, }; };
【解决方案3】:

我建议使用 Styled System 库,您可以将其与 Styled Components 或 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 代表 padding。

还有其他几个函数,例如 layout 用于宽度和高度之类的东西,'border'...

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

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

【讨论】:

    【解决方案4】:

    我有一个不同的解决方案 - 请注意,这仅适用于 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 将 style 属性优先于其 className 属性,因此您可以传入自定义样式。

    【讨论】:

      猜你喜欢
      • 2021-11-01
      • 2020-11-04
      • 1970-01-01
      • 2020-07-26
      • 2017-04-02
      • 2019-01-07
      • 2020-06-09
      • 2016-10-10
      • 2016-06-03
      相关资源
      最近更新 更多