Skip to content
On this page

Css in React

css 一直是 React 的痛点,也是被很多开发者吐槽、诟病的一个点。

在这一点上,Vue 做的要确实要好于 React:

  • Vue 通过在。vue 文件中编写 <style><style> 标签来编写自己的样式;
  • 通过是否添加 scoped 属性来决定编写的样式是全局有效还是局部有效;
  • 通过 lang 属性来设置你喜欢的 less、sass 等预处理器;
  • 通过内联样式风格的方式来根据最新状态设置和改变 css;
  • 等等。..

内联样式

内联样式是官方推荐的一种 css 样式的写法:

  • style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串;
  • 并且可以引用 state 中的状态来设置相关的样式;

优点

  1. 内联样式,样式之间不会有冲突
  2. 可以动态获取当前 state 中的状态

缺点

  1. 写法上都需要使用驼峰标识
  2. 某些样式没有提示
  3. 大量的样式,代码混乱
  4. 某些样式无法编写(比如伪类 / 伪元素)

代码

jsx
import React, { Component } from 'react'
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      color: "purple"
    }
  }
  render() {
    const pStyle = {
      color: this.state.color,
      textDecoration: "underline"
    }
    return (
      <div>
        <h2 style={{fontSize: "50px", color: "red"}}>我是标题</h2>
        <p style={pStyle}>我是一段文字描述</p>
      </div>
    )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

外部引用的 css

普通的 css 我们通常会编写到一个单独的文件,之后再进行引入。

这样的编写方式和普通的网页开发中编写方式是一致的:

  • 如果我们按照普通的网页标准去编写,那么也不会有太大的问题;
  • 但是组件化开发中我们总是希望组件是一个独立的模块,即便是样式也只是在自己内部生效,不会相互影响;
  • 但是普通的 css 都属于全局的 css,样式之间会相互影响;

代码

jsx
import React, { Component } from 'react';

import './style.css';

export default class Home extends Component {
  render() {
    return (
      <div className="home">
        <h2 className="title">我是home的标题</h2>
      </div>
    )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

css modules

Css Modules 并不是 React 专用解决方法,适用于所有使用 webpack 等打包工具的开发环境。以 webpack 为例,在 css-loader 的 options 里打开 modules:true 选项即可使用 Css Modules。

webpack.config.js

javascript
{
  loader: "css-loader",
  options: {
    importLoaders: 1,
    modules: true,
    localIdentName: "[name]__[local]___[hash:base64:5]"  // 为了生成类名不是纯随机
  },
},
1
2
3
4
5
6
7
8

css modules

.css/.less/.scss 等样式文件都修改成 .module.css/.module.less/.module.scss 等;

- style.module.css
- index.js
1
2

代码

jsx
import React, { Component } from 'react';
import appStyle from './style.module.css';

export default class App extends Component {
  render() {
    return (
      <div id="app">
        App
        <h2 className={appStyle.title}>我是App的title</h2>
      </div>
    )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

优点

css modules 确实解决了局部作用域的问题,也是很多人喜欢在 React 中使用的一种方案。

缺陷

  • 引用的类名,不能使用连接符 (.home-title),在 JavaScript 中是不识别的;
  • 所有的 className 都必须使用{style.className} 的形式来编写;
  • 不方便动态来修改某些样式,依然需要使用内联样式的方式;

CSS in JS

  • "CSS-in-JS" 是指一种模式,其中 CSS 由 JavaScript 生成而不是在外部文件中定义;
  • 注意此功能并不是 React 的一部分,而是由第三方库提供。 React 对样式如何定义并没有明确态度;

"Stop using CSS in JavaScript for web development"

styled-components

CSS-in-JS 的库中比较有特色的 - styled-components

基本使用

javascript
import styled from 'styled-components';

// `` 和 () 一样可以作为js里作为函数接受参数的标志,这个做法类似于HOC,包裹一层css到h1上生成新组件Title
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

const App = () => (
    <Wrapper bgColor='papayawhi'>
      <Title>Hello World, this is my first styled component!</Title>
    </Wrapper>
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

props、attrs 属性

props 可以被传递给 styled 组件

  • 获取 props 需要通过 ${}传入一个插值函数,props 会作为该函数的参数;
  • 这种方式可以有效的解决动态样式的问题;
jsx
const Wrapper = styled.section`
  padding: 4em;
  background: ${props => props.bgColor};
`;

const App = () => (
    <Wrapper bgColor='papayawhi'>
      <Title>Hello World, this is my first styled component!</Title>
    </Wrapper>
)
1
2
3
4
5
6
7
8
9
10

支持样式的继承

jsx
const JHButton = styled.button`
    padding: 8px 30px;
    border-radius: 5px;
`

const JHWarnButton = styled(JHButton)`
    background-color:red;
    color: #fff;
`
1
2
3
4
5
6
7
8
9

styled-jsx

个人感觉最类似 vue

yarn add styled-jsx 安装后,不用 import,而是一个 babel 插件,.babelrc 配置:

json
{
  "plugins": [
    "styled-jsx/babel"
  ]
}
1
2
3
4
5
jsx
render () {
    return <div className='table'>
        <div className='row'>
            <div className='cell'>A0</div>
            <div className='cell'>B0</div>
        </div>
        <style jsx>{`
          .table {
            margin: 10px;
          }
          .row {
            border: 1px solid black;
          }
          .cell {
            color: red;
          }
    `}</style>
    </div>;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
沪ICP备20006251号-1