React 官方对样式如何定义并没有明确的态度。
使用内联样式:
style 接收一个对象 style={{key: value, key: value}}
,属性名要使用小驼峰形式。
// 静态内联样式
<div style={{color: 'red', fontSize: 12}}></div>
// 动态内联样式
<div style={{color: `${this.state.isActive ? 'red' : ''}`, fontSize: 12}}></div>
优缺点:
优点:样式之间不会冲突;可以动态地获取当前 JS 中的变量。
缺点:写法上都需要使用驼峰标识;大量的样式会导致代码混乱;某些样式无法编写(比如:伪类、伪元素等);不支持 !important
的使用。
普通的外部样式表:
编写一个单独的样式文件进行引入,通常使用类选择器。不推荐使用。
// Home.jsx
import './Home.css'
class Home extends PureComponent {
render() {
return <h1 className='title'>Home</h1>
}
}
/* Home.css */
.title {
color: red;
}
// 静态 class
<div className="font12 colorRed"></div>
// 动态 class
<div className={this.state.isActive ? 'colorRed' : ''}></div>
// 静态 class 和动态 class 同时使用
<div className={`font12 ${this.state.isActive ? 'colorRed' : ''}`}></div>
优缺点:
缺点:CSS 作用于全局,样式之间会相互影响。
// Home.jsx
import './Home.css'
class Home extends PureComponent {
render() {
return <h1 className='title'>Home</h1>
}
}
/* Home.css */
.title {
color: red;
}
// App.jsx
// 即使 App.jsx 中根本没有引入 Home.css, Home.css 中的样式也会作用于 App.jsx
import Home from './Home/Home'
class App extends PureComponent {
render() {
return <h1 className='title'>App</h1>
}
}
CSS Modules:
.css
、.less
、.scss
等样式文件需要改成 .module.css
、.module.less
、.module.scss
等,就可以引入使用了。
CSS Modules 并不是 React 特有的解决方案,所有使用了类似 Webpack 配置的环境都可以使用。
React 脚手架已经内置了 CSS Modules 的配置。
// Home.jsx
import homeStyle from './Home.module.css'
class Home extends PureComponent {
render() {
return <h1 className={homeStyle.title}>Home</h1>
}
}
/* Home.module.css */
.title {
color: red;
}
CSS Modules 中类名是动态生成的,是由
文件的前缀名+ 类名 + 动态的哈希值
组成,来保证唯一性。
优缺点:
优点:解决了局部作用域的问题。
缺点:不方便动态修改样式。
CSS in JS:
CSS in JS 是一种模式,将样式 CSS 也写入到 JavaScript 中。CSS in JS 通过 JavaScript 来为 CSS 赋予一些能力,包括样式嵌套、函数定义、逻辑复用、动态修改状态等。推荐使用。
此功能并不是 React 的一部分,而是由第三方库提供。目前比较流行的库有:styled-components
、emotion
、glamorous
等。
使用 styled-components
:
styled-components
的本质是通过函数的调用,最终创建出一个组件,这个组件会被自动添加一个不重复的 class 类名。
styled-components
支持类似于 CSS 预处理器一样的样式嵌套;可以通过 &
符号获取当前元素。
- 安装
styled-components
:npm install styled-components
。 - 创建一个
style.js
文件编写 CSS。import styled from 'styled-components' // styled.div`` 是标签模板的用法,其实是一个函数的调用,会返回一个样式组件 // 可以通过 attrs 提供默认值 export const AppWrapper = styled.div.attrs(props => ({ headerBackgroundColor: props.headerBackgroundColor || 'green' }))` padding: 20px; /* 可以进行样式嵌套 */ .header { border: 1px solid black; .title { /* 可以接收到外部传入的 props。需写成一个函数,此回调函数会被自动调用并传入 props 作为参数 */ color: ${props => props.titleColor}; } /* 可以使用 & 获取到当前元素 */ &:hover { background: ${props => props.headerBackgroundColor}; } } `
- 引入使用
style.js
。import {AppWrapper} from './style.js' class App extends PureComponent { state = { titleColor: 'red', } render() { const {titleColor} = this.state return ( // 使用 AppWrapper 包裹想要设置样式的内容,并且可以传入属性 <AppWrapper titleColor={titleColor}> <div className='header'> <h1 className='title'>App</h1> </div> </AppWrapper> ) } }