Appearance
Css in React
css 一直是 React 的痛点,也是被很多开发者吐槽、诟病的一个点。
在这一点上,Vue 做的要确实要好于 React:
- Vue 通过在。vue 文件中编写
<style><style>标签来编写自己的样式; - 通过是否添加 scoped 属性来决定编写的样式是全局有效还是局部有效;
- 通过 lang 属性来设置你喜欢的 less、sass 等预处理器;
- 通过内联样式风格的方式来根据最新状态设置和改变 css;
- 等等。..
内联样式
内联样式是官方推荐的一种 css 样式的写法:
- style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串;
- 并且可以引用 state 中的状态来设置相关的样式;
优点
- 内联样式,样式之间不会有冲突
- 可以动态获取当前 state 中的状态
缺点
- 写法上都需要使用驼峰标识
- 某些样式没有提示
- 大量的样式,代码混乱
- 某些样式无法编写(比如伪类 / 伪元素)
代码
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
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
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
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
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
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
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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20