> For the complete documentation index, see [llms.txt](https://zg-zhang.gitbook.io/note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zg-zhang.gitbook.io/note/shi-zhan-bi-ji/cloud-music-web-app-v1.0/styled-components.md).

# styled-components: all in js

> styled-components 是一个给 React 量身定制的一个库，奉行 React 中 all in js 的设计理念，并发挥到极致，让 CSS 也能称为一个个 JS 模块。

## 使用 styled-components 解决了哪些痛点？

### CSS 模块化

尽量降低模块之间的耦合度，利于项目的进一步维护

### 支持预处理器嵌套语法

可以采用 sass、less 的嵌套语法

```javascript
export const SearchWrapper = styled.div`
    position: relative;
    float: left;
    .zoom {
        right: 5px;
        &.focused {
            background: #777;
            color: #fff;
        }
    }
`;
```

### 让 CSS 代码能够处理逻辑

不仅仅是因为里面的模板字符串可以写 JS 表达式，更重要的是能够拿到组件的上下文信息 state、props

比如：在 React 组件中的 JSX 代码中写了这样一段：

```jsx
<RecommendItem imgUrl={'xxx'}/>
```

在相应的 style.js 中就能够接受相应的参数：

```javascript
export const RecommendItem = styled.div`
    width: 280px;
    height: 50px;
    background: url(${(props) => props.imgUrl});
    background-size: contain;
`
```

### 语义化

> 前端开发者的毒药，致命一击

```jsx
// index.jsx
<HeaderWrapper>
    <Logo/>
    <Nav>
        <NavItem className='left active'>首页</NavItem>
        <NavItem className='left'>下载App</NavItem>
        <NavItem className='right'>
            <i className="iconfont">&#xe636;</i>
        </NavItem>
        <SearchWrapper>
            <NavSearch></NavSearch>
            <i className='iconfont'>&#xe614;</i>
        </SearchWrapper>
    </Nav>
    <Addition>
        <Button className='writting'>
          <i className="iconfont">&#xe615;</i>
          来参加
        </Button>
        <Button className='reg'>注册</Button>
    </Addition>
</HeaderWrapper>
```

```jsx
//index.js
import styled from 'styled-components';

export const HeaderWrapper = styled.div`
    z-index: 1;
    position: relative;
    height: 56px;
    border-bottom: 1px solid #f0f0f0;
`;

export const Logo = styled.div`
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    width: 100px;
    height: 56px;
    background: url(${logoPic});
    background-size: contain;
`;

export const Nav = styled.div`
    width: 960px;
    height: 100%;
    padding-right: 70px;
    box-sizing: border-box;
    margin: 0 auto;
`;
//......
```

可以发现，拆分后的标签基本是在 style.js 里面导出的变量名，完全自定义，这个时候 CSS 都成为了一个个 JS 模块，每个模块相当于一个标签

如：styled.div 已经帮我们创建好了标签

在模块下面完全可以再写 h5 标签，开发方式更灵活

## 使用方法

[基本知识](broken://pages/-M5WJkdVrKXYLi0KmjKu)

[高级用法](broken://pages/-M5YrYJFPt88KpEtT8S9)

[API](broken://pages/-M5Z0wXvS7Oxgqg3K5ls)

## 开发踩的坑以及目前的缺点

* 坑：以前的 injectGlobal 已经被弃用，对于全局样式文件需要使用 createGlobalStyle 来进行引入

```javascript
//iconfont.js
//全局样式同理
import {createGlobalStyle} from 'styled-components'

export const IconStyle = createGlobalStyle`
@font-face {
  font-family: "iconfont";
  src: url('./iconfont.eot?t=1561883078042'); /* IE9 */
  src: url('./iconfont.eot?t=1561883078042#iefix') format('embedded-opentype'), /* IE6-IE8 
  //...
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
`
```

然后在全局的根组件 APP.js 里面：

```jsx
import { IconStyle } from './statics/iconfont/iconfont'
import { GlobalStyle } from  './style'
//import ...

function App() {
  return (
    <Provider store={store}>
      <div>
        {/* 通过标签形式引入这些样式 */}
        <GlobalStyle></GlobalStyle>
        <IconStyle></IconStyle>
        <Header />
        <BrowserRouter>
        <div>
          <Route path='/' exact component={Home}></Route>
          <Route path='/detail' exact component={Detail}></Route>
        </div>
        </BrowserRouter>
      </div>
    </Provider>
  );
}

export default App;
```
