美文网首页
React之css解决方案Styled-Components

React之css解决方案Styled-Components

作者: Yokiijay | 来源:发表于2019-01-30 09:02 被阅读0次

    感谢 Liang Wang 提供中文翻译文档
    https://github.com/hengg/styled-components-docs-zh/blob/master/Basics.md
    我在这里精简一下基础部分,方便快速回顾知识,没学过的还是建议先看文档

    安装 yarn add styled-components

    引入 import styled from 'styled-components'

    先来个最基础的例子


    // 创建一个 Title 组件,它将渲染一个附加了样式的 <h1> 标签
    const Title = styled.h1`
      font-size: 1.5em;
      text-align: center;
      color: palevioletred;
    `;
    
    // 创建一个 Wrapper 组件,它将渲染一个附加了样式的 <section> 标签
    const Wrapper = styled.section`
      padding: 4em;
      background: papayawhip;
    `;
    
    // 就像使用常规 React 组件一样使用 Title 和 Wrapper 
    render(
      <Wrapper>
        <Title>
          Hello World!
        </Title>
      </Wrapper>
    );
    

    先解析第一行 styled 是引入的styled,.后面的是你要创建的标签名,` `中间包裹的就是正常的CSS样式(可以写变量,传props值,后面会讲到),然后你这些复制给一个大写开头的Title变量,那么Title在styled的作用下就变成了一个组件,直接把组件渲染出来就可以了

    基于属性的适配


    const Button = styled.button`
      /* Adapt the colors 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;
    `;
    
    render(
      <div>
        <Button>Normal</Button>
        <Button primary>Primary</Button>
      </div>
    );
    

    样式继承


    const Button = styled.button`
      color: palevioletred;
      font-size: 1em;
      margin: 1em;
      padding: 0.25em 1em;
      border: 2px solid palevioletred;
      border-radius: 3px;
    `;
    
    // 一个继承 Button 的新组件, 重载了一部分样式
    const TomatoButton = styled(Button)`
      color: tomato;
      border-color: tomato;
    `;
    
    render(
      <div>
        <Button>Normal Button</Button>
        <TomatoButton>Tomato Button</TomatoButton>
      </div>
    );
    

    多态 "as" polymorphic prop


    const Button = styled.button`
      display: inline-block;
      color: palevioletred;
      font-size: 1em;
      margin: 1em;
      padding: 0.25em 1em;
      border: 2px solid palevioletred;
      border-radius: 3px;
    `;
    
    const TomatoButton = styled(Button)`
      color: tomato;
      border-color: tomato;
    `;
    
    render(
      <div>
        <Button>Normal Button</Button>
        <Button as="a" href="/">Link with Button styles</Button>
        <TomatoButton as="a" href="/">Link with Tomato Button styles</TomatoButton>
      </div>
    );
    

    这也完美适用于自定义组件:

    const Button = styled.button`
      display: inline-block;
      color: palevioletred;
      font-size: 1em;
      margin: 1em;
      padding: 0.25em 1em;
      border: 2px solid palevioletred;
      border-radius: 3px;
    `;
    
    const ReversedButton = props => <button {...props} children={props.children.split('').reverse()} />
    
    render(
      <div>
        <Button>Normal Button</Button>
        <Button as={ReversedButton}>Custom Button with Normal Button styles</Button>
      </div>
    );
    

    给任何组件添加样式


    styled方法适用于任何最终向 DOM 元素传递 className 属性的组件,当然也包括第三方组件.
    
    注意
    
    在 react-native 中,请使用 style 而不是 className.
    
    // 下面是给 react-router-dom  Link 组件添加样式的示例
    const Link = ({ className, children }) => (
      <a className={className}>
        {children}
      </a>
    );
    
    const StyledLink = styled(Link)`
      color: palevioletred;
      font-weight: bold;
    `;
    
    render(
      <div>
        <Link>Unstyled, boring Link</Link>
        <br />
        <StyledLink>Styled, exciting Link</StyledLink>
      </div>
    );
    

    也可以传递标签给styled(), 比如: styled("div"). 实际上styled.tagname的方式就是 styled(tagname)`的别名.

    属性传递


    const Input = styled.input`
      padding: 0.5em;
      margin: 0.5em;
      color: ${props => props.inputColor || "palevioletred"};
      background: papayawhip;
      border: none;
      border-radius: 3px;
    `;
    
    // 渲染两个样式化的 text input,一个标准颜色,一个自定义颜色
    render(
      <div>
        <Input defaultValue="@probablyup" type="text" />
        <Input defaultValue="@geelen" type="text" inputColor="rebeccapurple" />
      </div>
    );
    

    注意, inputColor prop并没有传递给 DOM, 但是type和defaultValue 都传递了. styled-components足够智能,会自动过滤掉所有非标准 attribute.

    styled-components 如何在组件中工作?


    Styled Component 是 HTML 元素和作用在元素上的样式规则的组合, 我们可以这样编写Counter:

    import React from 'react'
    import styled from 'styled-components'
    
    const StyledCounter = styled.div`
      /* ... */
    `
    const Paragraph = styled.p`
      /* ... */
    `
    const Button = styled.button`
      /* ... */
    `
    
    export default class Counter extends React.Component {
      state = { count: 0 }
    
      increment = () => this.setState({ count: this.state.count + 1 })
      decrement = () => this.setState({ count: this.state.count - 1 })
    
      render() {
        return (
          <StyledCounter>
            <Paragraph>{this.state.count}</Paragraph>
            <Button onClick={this.increment}>+</Button>
            <Button onClick={this.decrement}>-</Button>
          </StyledCounter>
        )
      }
    }
    

    伪元素,伪类选择器和嵌套


    styled-component 所使用的预处理器stylis支持自动嵌套的 scss-like 语法,示例如下:

    const Thing = styled.div`
      color: blue;
    `
    

    伪元素和伪类无需进一步细化,而是自动附加到了组件:

    const Thing = styled.button`
      color: blue;
    
      ::before {
        content: '🚀';
      }
    
      :hover {
        color: red;
      }
    `
    
    render(
      <Thing>Hello world!</Thing>
    )
    

    对于更复杂的选择器,可以使用与号(&)来指向主组件.以下是一些示例:


    const Thing = styled.div.attrs({ tabIndex: 0 })`
      color: blue;
    
      &:hover {
        color: red; // <Thing> when hovered
      }
    
      & ~ & {
        background: tomato; // <Thing> as a sibling of <Thing>, but maybe not directly next to it
      }
    
      & + & {
        background: lime; // <Thing> next to <Thing>
      }
    
      &.something {
        background: orange; // <Thing> tagged with an additional CSS class ".something"
      }
    
      .something-else & {
        border: 1px solid; // <Thing> inside another element labeled ".something-else"
      }
    `
    

    如果只写选择器而不带&,则指向组件的子节点.

    const Thing = styled.div`
      color: blue;
    
      .something {
        border: 1px solid; // an element labeled ".something" inside <Thing>
        display: block;
      }
    `
    
    render(
      <Thing>
        <label htmlFor="foo-button" className="something">Mystery button</label>
        <button id="foo-button">What do I do?</button>
      </Thing>
    )
    

    附加额外的属性 (v2)


    为了避免仅为传递一些props来渲染组件或元素而使用不必要的wrapper, 可以使用 .attrs constructor. 通过它可以添加额外的 props 或 attributes 到组件.

    举例来说,可以通过这种方式给元素添加静态 props,或者传递第三方 prop 给组件(比如传递activeClassName给 React Router 的 Link). 此外也可以将dynamic props 添加到组件. .attrs 对象也接收函数,返回值也将合并进 props.

    示例如下:

    source-js-jsx
    const Input = styled.input.attrs({
      //  static props
      type: "password",
    
      //  dynamic props
      margin: props => props.size || "1em",
      padding: props => props.size || "1em"
    })`
      color: palevioletred;
      font-size: 1em;
      border: 2px solid palevioletred;
      border-radius: 3px;
    
      /* dynamically computed props */
      margin: ${props => props.margin};
      padding: ${props => props.padding};
    `;
    
    render(
      <div>
        <Input placeholder="A small text input" size="1em" />
        <br />
        <Input placeholder="A bigger text input" size="2em" />
      </div>
    );
    

    动画


    虽然使用@keyframes的 CSS 动画不限于单个组件,但我们仍希望它们不是全局的(以避免冲突). 这就是为什么 styled-components 导出 keyframes helper 的原因: 它将生成一个可以在 APP 应用的唯一实例:

    // Create the keyframes
    const rotate = keyframes`
      from {
        transform: rotate(0deg);
      }
    
      to {
        transform: rotate(360deg);
      }
    `;
    
    // Here we create a component that will rotate everything we pass in over two seconds
    const Rotate = styled.div`
      display: inline-block;
      animation: ${rotate} 2s linear infinite;
      padding: 2rem 1rem;
      font-size: 1.2rem;
    `;
    

    Thank you, that's all for Basics!

    相关文章

      网友评论

          本文标题:React之css解决方案Styled-Components

          本文链接:https://www.haomeiwen.com/subject/djrqsqtx.html