【问题标题】:React Styled component: how to add css styles based on props?React Styled 组件:如何根据 props 添加 css 样式?
【发布时间】:2018-12-31 14:08:14
【问题描述】:

我一直在努力寻找解决问题的方法。 我在自己的文件中有几个标题标签(H1、H2 等)。 我想在基于道具调用它们时添加一些 CSS。有些标题有一个小的边框底部,有些则没有。所以,为了重构我的代码,我想添加一些基于道具的 css。我似乎找不到方法。

这是标题 H2 的示例:

import styled from 'styled-components';
import colors from '../../../../colors'; 
import fonts from '../../../../fonts';
import fontWeights from '../../../../fontWeights';

const HeadingH2 = styled.h2`
  color: ${colors.text};
  font-family: ${fonts.montSerrat};
  font-size: 1.6em;
  font-weight: ${fontWeights.light};
  letter-spacing: 0.2em;
  padding-bottom: 0.7em;
  position: relative;
  text-transform: uppercase;
  text-align: center;
  &:after{
    content: "";
    display: block;
    height: 3px;
    width: 45px;
    background-color: currentColor;
    /* position */
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
  }
`;

export default HeadingH2

Heading H2 调用示例:

import React from 'react';
import HeadingH2 from '../../common/headings/heading_h2';
import HeadingBaseline from '../../common/headings_baseline';


// Features
import {SectionContainer, FeaturesContainer} from './features.style';

import Feature from './feature';
import feature1 from '../../../img/features/feature1.png';
import feature2 from '../../../img/features/feature2.png';
import feature3 from '../../../img/features/feature3.png';

// Text
import Text from '../../../content';

const Features = () => {
  return(
    <SectionContainer id={"what"}>
      <HeadingH2>
        What We Do
      </HeadingH2>
    <HeadingBaseline>
      {Text.headingBaseline}
    </HeadingBaseline>
  <FeaturesContainer>
    <Feature 
      src={feature1} 
      headingText={Text.feature1.heading}
      paragraph={Text.feature1.paragraph}
      />
    <Feature 
      src={feature2} 
      headingText={Text.feature2.heading}
      paragraph={Text.feature2.paragraph}
      />
    <Feature 
      src={feature3} 
      headingText={Text.feature3.heading}
      paragraph={Text.feature3.paragraph}
      />
  </FeaturesContainer>
</SectionContainer>
)
};

export default Features;

我想提取以下 CSS 属性

position: relative;
text-transform: uppercase;
text-align: center;
&:after{
 content: "";
 display: block;
 height: 3px;
 width: 45px;
 background-color: currentColor;
 /* position */
 position: absolute;
 bottom: 0;
 left: 50%;
 transform: translateX(-50%);

所以,假设我在一个单独的文件中有上述 CSS 规则,我如何使用我的样式组件 HeadingH2 上的道具添加/导入它们。

感谢您的帮助:)

【问题讨论】:

  • 我从未使用过样式组件,但似乎有一个您想要做的示例on the library's homepage。本质上,样式化组件在构建 CSS 字符串时可以访问道具,您可以根据它们覆盖/添加样式。
  • 不完全。我需要能够随时从特定文件中添加 css 规则。主页上的示例根本不是模块化的。

标签: javascript reactjs


【解决方案1】:

您还可以使用来自styled-componentscss 助手来创建SharedStyles.js 文件。

demo 中,您可以看到它的实际效果。 仅以继承组件的样式使用它并不能按预期工作。如果我将其添加到StyledBase,则之后不会正确添加变量(悬停样式覆盖停止工作)。 这就是为什么我将 ${borderBottom} 复制到每个样式组件 Heading1 / Heading2 而不是将其添加到 StyledBase

我认为为标题设置级别道具是个好主意,但我会通过创建 HeadingBase 组件并将您的样式添加到 StyledBase 组件来以不同的方式处理它(另请参见演示中的代码)。

HeadingBase 代码如下所示:

const HeadingBase = ({ className, children, level = 1 }) =>
    React.createElement(`h${level}`, { className }, children);

它是一个组件,它根据传递的 level 属性(默认为 h1)呈现 h1、h2、... 标签。 h-tag 接收className 作为道具(样式组件需要)并包含传递给组件的子项。

SharedStyles.js

import { css } from "styled-components";

export const borderBottom = css`
    &:after{
        content: "";
        display: block;
        height: 3px;
        width: 200px;
        background-color: ${props => props.color || "black"};
        /* position */
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
`;

然后您可以使用import { borderBottom } from "./SharedStyles"; 导入它并将其添加到您的样式组件中,如下所示:

const Heading1= styled.h1`
    ${borderBottom}
`;

【讨论】:

    【解决方案2】:

    这样的工作:

    const HeadingH2 = styled.h2`
      position: ${props => props.relative && 'relative'};
      padding: ${props => props.paddingBottom ? '0 0 20px 0' : '0'};
    }
    `;
    

    然后像这样使用:

    <HeadingH2 relative paddingBottom />
    

    【讨论】:

    • 我需要找到一种方法来从单独的文件中调用这些 css 属性或减少代码重复
    • 这是与styled-components一起使用props的最佳答案
    • @allan00958 您可以导入样式化组件。您可以在使用组件时使用 React Props 更改属性。
    • @allan00958 如果对您有用,请将此答案标记为正确:) 谢谢!
    • @jsw324 不,这个答案对我根本不起作用。我在下面发布了我的解决方案。
    【解决方案3】:

    可能的答案:

    我像这样在一个单独的文件中添加以下 CSS 规则。 我创建了一个返回文本字符串的函数。我可以导入这个函数并将这些规则添加到我希望的任何组件中。

    export const borderBottom = () => {
      return `
       position: relative;
       text-transform: uppercase;
       text-align: center;
       &:after{
        content: "";
        display: block;
        height: 3px;
        width: 45px;
        background-color: currentColor;
        /* position */
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
      } 
    `
     }
    

    并在我希望的任何标题或组件上使用它:

    import styled from 'styled-components';
    import colors from '../../../../colors';
    import fonts from '../../../../fonts';
    import fontWeights from  '../../../../fontWeights';
    import {borderBottom} from '../../../../css';
    
    const HeadingH5 = styled.h5`
      color: ${colors.black};
      font-family: ${fonts.montSerrat};
      font-size: 1em;
      font-weight: ${fontWeights.light};
      letter-spacing: 0.1em;
      padding-bottom: 0.45em;
      margin-bottom: 25px;
      ${borderBottom}
    `  
    ;
    
    export default HeadingH5;
    

    这对我有用。欢迎任何其他建议。

    【讨论】:

    • 您能解释一下解决方案吗?很高兴您为自己的问题提供了答案,但如果您希望其他人从中受益,您应该解释您为解决问题所做的工作以及原因。如果您将此作为您自己问题的延续发布,请改为更新问题。
    • 我创建了一个函数,它将一些 CSS 属性/值作为字符串返回,并使用字符串替换将它们导入/导出到我希望的任何样式组件中。这样我的代码是枯燥和模块化的。
    【解决方案4】:

    你应该明确地检查这个:typestyle

    编写动态 CSS 的最佳方式(对我而言)。与 react 完美配合,即使需要 ssr...

    【讨论】:

      【解决方案5】:

      为什么不直接使用 headingLevel 属性?然后将其传递给样式组件?并且只有一个StyledHeader 样式的组件,因为我猜代码在所有标题样式文件中几乎相同?这是一个很大的不,你想总是尽量不要重复你的代码。

      const Features = () => {
        return(
          <SectionContainer id={"what"}>
            <StyledHeader
              headingLevel={headingLevel}
            >
              What We Do
            </StyledHeader>
          <HeadingBaseline>
            {Text.headingBaseline}
          </HeadingBaseline>
        <FeaturesContainer>
          <Feature 
            src={feature1} 
            headingText={Text.feature1.heading}
            paragraph={Text.feature1.paragraph}
            />
          <Feature 
            src={feature2} 
            headingText={Text.feature2.heading}
            paragraph={Text.feature2.paragraph}
            />
          <Feature 
            src={feature3} 
            headingText={Text.feature3.heading}
            paragraph={Text.feature3.paragraph}
            />
        </FeaturesContainer>
      </SectionContainer>
      )
      };
      
      export default Features;
      

      在您的StyledHeader 文件中

      下面的函数将把你传入的标题级别h1h2h3 应用一个边框,如果不是上面的 3 个标题级别,它将是 0 值。我会做一些检查以确保该值是小写的,例如toLowerCase()

      const getBorder = ({ headingLevel } ) => {
        const headingLevelMap = {
          h1: 0.7,
          h2: 0.6,
          h3: 0.6,
        };
      
        return headingLevelMap[headingLevel] || 0;
      }
      
      const HeadingH2 = styled.headingLevel`
        color: ${colors.text};
        font-family: ${fonts.montSerrat};
        font-size: 1.6em;
        font-weight: ${fontWeights.light};
        letter-spacing: 0.2em;
        padding-bottom: 0.7em;
        border-bottom: ${getCorrectBorderBottom}em solid black
        position: relative;
        text-transform: uppercase;
        text-align: center;
        &:after{
          content: "";
          display: block;
          height: 3px;
          width: 45px;
          background-color: currentColor;
          /* position */
          position: absolute;
          bottom: 0;
          left: 50%;
          transform: translateX(-50%);
        }
      `;
      

      我还要检查,如果传入的 headingLevel 的值不是 6 个标题级别中的任何一个,它应该有一个你想要的默认值。

      以上只是快速的伪代码,但希望在这里得到大致的想法?如果没有,请告诉我它。

      我还建议您将 Title 组件拆分为一个单独的组件。

      【讨论】:

      • 我有点明白,但我认为这不是正确的解决方案。我发现了一些可以使用连接的东西。我会更新我原来的问题。
      • 我发布了我的解决方案
      猜你喜欢
      • 2021-03-07
      • 2020-05-01
      • 2018-07-01
      • 2018-12-14
      • 2019-01-17
      • 2020-06-09
      • 2021-01-05
      • 2020-04-19
      • 2018-11-23
      相关资源
      最近更新 更多