【问题标题】:React — Passing props with styled-componentsReact — 使用 styled-components 传递 props
【发布时间】:2019-02-18 15:37:37
【问题描述】:

我刚刚在styled-components documentation 中读到以下内容是错误的,它会影响渲染时间。如果是这样,我该如何重构代码并使用所需的道具来创建动态样式?

提前谢谢你。

标签组件

import React from 'react'
import styled from 'styled-components'

const Tab = ({ onClick, isSelected, children }) => {
    const TabWrapper = styled.li`
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 100px;
    margin: 1px;
    font-size: 3em;
    color: ${props => (isSelected ? `white` : `black`)};
    background-color: ${props => (isSelected ? `black` : `#C4C4C4`)};
    cursor: ${props => (isSelected ? 'default' : `pointer`)};
`

    return <TabWrapper onClick={onClick}>{children}</TabWrapper>
}


export default Tab

【问题讨论】:

    标签: javascript reactjs styled-components


    【解决方案1】:

    我相信文档所说的是你应该避免在渲染组件中包含你的样式:

    这样做

    const StyledWrapper = styled.div`
      /* ... */
    `
    
    const Wrapper = ({ message }) => {
      return <StyledWrapper>{message}</StyledWrapper>
    }
    

    取而代之

    const Wrapper = ({ message }) => {
      // WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
      const StyledWrapper = styled.div`
        /* ... */
      `
    
      return <StyledWrapper>{message}</StyledWrapper>
    }
    

    因为当组件的 Props 发生变化时,组件会重新渲染,样式会重新生成。因此,将其分开是有意义的。

    因此,如果您进一步阅读基于道具改编部分,他们会解释:

    const Button = styled.button`
      /* Adapt the colours based on primary prop */
      background: ${props => props.primary ? "palevioletred" : "white"};
      color: ${props => props.primary ? "white" : "palevioletred"};
    
      font-size: 1em;
      margin: 1em;
      padding: 0.25em 1em;
      border: 2px solid palevioletred;
      border-radius: 3px;
    `;
    
    // class X extends React.Component {
    //  ...
    
    render(
      <div>
        <Button>Normal</Button>
        <Button primary>Primary</Button>
      </div>
    );
    
    // }
    

    这是因为当你在 class X 中使用 Button 组件时,它会知道 class X 的 props 而无需你告诉它任何事情。

    对于您的情况,我想解决方案很简单:

    const TabWrapper = styled.li`
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 100px;
      margin: 1px;
      font-size: 3em;
      color: ${props => (props.isSelected ? `white` : `black`)};
      background-color: ${props => (props.isSelected ? `black` : `#C4C4C4`)};
      cursor: ${props => (props.isSelected ? 'default' : `pointer`)};
    `;
    
    const Tab = ({ onClick, isSelected, children }) => {
      return <TabWrapper onClick={onClick}>{children}</TabWrapper>
    }
    
    const X = <Tab onClick={() => console.log('clicked')} isSelected>Some Children</Tab>
    

    我根本没有测试过这个,所以请随意尝试一下,让我知道它是否适合你或任何适合你的方法!

    【讨论】:

    • 这对我有帮助。
    【解决方案2】:

    您可以使用 Typescript 传递参数,如下所示:

    <StyledPaper open={open} />    
    
    ...
    
    const StyledPaper = styled(Paper)<{ open: boolean }>`
       top: ${p => (p.open ? 0 : 100)}%;
    `;
    

    【讨论】:

      【解决方案3】:

      另一种方法是

      const StyledDiv = styled.div.attrs((props: {color: string}) => props)`
          width: 100%;
          height: 100%;
          background-color: ${(props) => props.color};
      `
      
      //...
      
      render() {
          return (
              <StyledDiv color="black">content...</StyledDiv>
          );
      }
      

      这样,就要发送到样式组件的道具而言,您是类型安全的。 (在 Typescript 中编码时很好)

      【讨论】:

      • 这是一个很好的解决方案,因为它遵循最佳实践并为我工作
      • 感谢您添加此类型安全性,非常有帮助!
      【解决方案4】:

      如果您使用的是 Typescript,请在​​样式文件中创建一个界面! 否则,您将无法访问 CSS 中的 props

      import styled from 'styled-components'
      
      interface StyledLiProps{
        selected: boolean
      }
      
      export const TabWrapper = styled.li`
          
      // styles ...
      
      color: ${props => (selected ? `white` : `black`)};
      background-color: ${props => (selected ? `black` : `#C4C4C4`)};
      `
      
      

      别忘了在你的 JSX 中声明你想在 CSS 中使用的 props

      interface TabProps{
        text: string;
      }
      
      const Tab = ({ text }: TabProps) => {
       
      //...
        
      return <TabWrapper selected={isSelected} onClick={() => updateTab}>{text}</TabWrapper>
      
      
      }
      

      【讨论】:

        【解决方案5】:

        关于功能组件的更简单示例:

        假设您有一个像多边形一样的箭头,并且您需要其中 2 个指向不同的方向。所以可以通过 props 传递旋转值

                       <Arrow rotates='none'/>
                  
                       <Arrow rotates='180deg'/>
        

        然后在组件箭头中,您必须像普通组件一样将道具传递给样式组件,但在样式组件中您必须像道具一样使用它:

            import React from 'react';
            import styled from "@emotion/styled";
        
            const ArrowStyled = styled.div`
              background-color: rgba(255,255,255,0.9);
              width: 24px;
              height: 30px;
              clip-path: polygon(56% 40%,40% 50%,55% 63%,55% 93%,0% 50%,56% 9%);
              transform: rotate(${props => props.rotates});
             `
        
        
        const Arrow = ({rotates}) => {
            return (
               <ArrowStyled rotates={rotates}/>
            );
        }
        
        export default Arrow;
                   
        

        【讨论】:

          【解决方案6】:

          考虑样式化组件文档提供了针对不同主题使用 reacts context api [2] 的示例。

          [1]https://www.styled-components.com/docs/advanced

          [2]https://reactjs.org/docs/context.html

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-28
            • 2020-03-02
            • 2017-12-21
            • 2020-07-09
            • 2019-10-07
            • 2021-09-22
            • 2018-04-27
            • 2021-09-19
            相关资源
            最近更新 更多