样式组件的多个道具选项

Multiple Props Options for Styled Components

我有一个使用样式化组件创建的导航栏组件。我想创建一些道具来改变背景颜色 and/or 文本颜色。

例如:<Navbar dark> 应该有以下 CSS:

background: #454545;
color: #fafafa;

<Navbar light>应该是相反的:

background: #fafafa;
color: #454545;

但是,如果两个道具都没有使用,那么我想要一个默认的背景和文本颜色——比如(出于演示目的),像这样:

background: #eee;
color: #333;

现在,我的问题是如何在样式化组件中进行设置。

我可以做到以下几点:

background: ${props => props.dark ? #454545 : '#eee'}
background: ${props => props.dark ? #fafafa : '#eee'}
background:  #eee;

颜色也类似。

但是这是多余的而且不是很优雅。我想要某种 if/else 语句:

background: ${ props => { 
  if (props.dark) { #454545 }
  elseif (props.light) { #fafafa }
  else { #eee }
}

但我不知道如何在样式组件中设置类似的东西。

有什么建议吗?

提前致谢。

保持传入的 prop 名称相同。然后你可以使用 switch/case 语句。例如,传入 color 属性并将其用作 type 以匹配 case.

工作示例:


例如:

<Button color="primary">Example</Button>

components/Button

import styled from "styled-components";

const handleColorType = color => {
  switch (color) {
    case "primary":
      return "#03a9f3";
    case "danger":
      return "#f56342";
    default:
      return "#fff";
  }
};

const Button = styled.button`
  display: block;
  cursor: pointer;
  border: 0;
  margin: 5px 0;
  background: #000;
  font-size: 20px;
  color: ${({ color }) => handleColorType(color)};

  &:focus {
    outline: 0;
  }
`;

export default Button;

如果您有多个属性(如一对 color 和一对 background),则使用与上述相同的概念,将 handleColorType 更改为 return string 具有属性并调用 handleColorType 函数 没有 样式 属性.

例如:

<MultiButton color="primary">Example</MultiButton>

components/MultiButton

import styled from "styled-components";

const handleColorType = color => {
  switch (color) {
    case "primary":
      return "color: #03a9f3; background: #000;";
    case "danger":
      return "color: #fff; background: #f56342;";
    default:
      return "color: #000; background: #eee;";
  }
};

const MultiButton = styled.button`
  display: block;
  margin: 5px 0;
  cursor: pointer;
  border: 0;
  font-size: 20px;
  ${({ color }) => handleColorType(color)};

  &:focus {
    outline: 0;
  }
`;

export default MultiButton;

这是我最终使用的解决方案:

export const Navbar = styled.nav`
  width: 100%;

  ...  // rest of the regular CSS code

  ${props => {
    if (props.dark) {
      return `
        background: ${colors.dark};
        color: ${colors.light};
    `
    } else if (props.light) {
      return `
        background: ${colors.light};
        color: ${colors.dark};
    `
    } else {
      return `
        background: ${colors.light};
        color: ${colors.dark};
    `
    }
  }}
`

你也可以这样做:


 const colorType= {
   dark: '#454545',
   light: '#0a0a0a',
   normal: '#dedede'
};



export const Navbar= styled.nav`
   background: ${({color}) => colorType[color] || `${color}`};

`;

给你:

<Navbar color="primary" />
<Navbar color="#FFFFFF" />

更优雅(我猜)和现代的东西是解构道具和使用 switch 语句的组合,例如:

const Button = styled.button`
  ${({primary, secondary}) => {
      switch(true) {
        case primary:
          return `background-color : green`
        case secondary:
          return `background-color : red`
      }
    }
  }
`

样式化组件还接受一个函数,您可以在其中读取道具。此外,如果您选择传递一个主题道具,您还可以为您的主题定义一个对象。


const themes = {
  dark: css `
     background: ${colors.dark};
     color: ${colors.light};
  `,
  light: css`
     background: ${colors.light};
     color: ${colors.dark};
  `
}
export const Navbar = styled.nav(({theme})=>`
  width: 100%;
  background: ${colors.light};
  color: ${colors.dark};
  ... // rest of the css

  ${theme?themes[theme]:''}

  `)

<Navbar theme="dark" />

解决方案使用Styled-tools

在你的具体情况下

因为你只有两个主题,一个是默认的light,一个是你可以切换的dark,你只需要检查它是否是黑暗模式。

import {ifProp} from "styled-tools";

export const Navbar = styled.nav`
  ${ifProp("dark",
    css`
      background: ${colors.dark};
      color: ${colors.light};
    `,
    css`
      background: ${colors.light};
      color: ${colors.dark};
    `,

  )}
`;

并使用 <Navbar $dark={isDarkMode} />

渲染

更通用的解决方案

当然,您仍然想使用 dark/light 等主题方法。设置变体会让事情变得更容易。例如,您可以在单独的枚举中跟踪您想要的不同主题。像这样:

enum Themes {
    DARK = "dark",
    LIGHT = "light",
}

稍后在您的样式中您可以指定:

import {switchProp} from "styled-tools";

export const Navbar = styled.nav`
  ${switchProp({
    dark: css`
      background: ${colors.dark};
      color: ${colors.light};
    `,
    light: css`
      background: ${colors.light};
      color: ${colors.dark};
    `,

  })}
`;

然后渲染 <Navbar variant={Theme.LIGHT} /><Navbar variant={Theme.DARK} />

参考资料

怎么样:

const StyledButton = styled.button`
    padding: 8px 16px;
    border-radius: ${props => props.rounded ? '10px' : '0px'};
    ${props => {
        switch (props.type) {
            case 'primary':
                return `
                    background-color : #000;
                    color: #fff;
                    border: 1px solid #000000;
                `;
            case 'secondary':
                return `
                    background-color : #DEDEDE;
                    border: 1px solid #999;
                `;
        }
    }
}`;