react这个库其实在css这方面并没有vue做的好,因为vue的SFC(单文件组件)把HTML、CSS、JavaScript都集成在了一个文件里,并且提供了scoped为每个页面提供了独一无二的css作用域。而react并没有在一个页面中集成CSS,因此,我们在react中使用CSS是开放性的,每种方案都各有优势。
第一种:全局CSS
我们可以声明一个CSS文件,在里面书写我们需要的样式,然后在主文件当中引入,这样webpack就会编译这个文件,这样样式就会生效了。
.title {
color: red;
font-size: 30px;
}
.content {
color: orange;
font-size: 20px;
}
当然了,这种写法的缺陷就是样式是全局共享的,我们无法避免样式冲突的情况,并且现在的需求如此复杂,有时我们需要使用JS来控制CSS时,这种方案明显无法做到。
第二种:内联CSS
我们可以像在普通的html文件中写内联样式一样在react中写内联样式,区别就是react中我们是在一个jsx中写,因此这里的style应该是一个表达式。以下就是例子:
export class App extends PureComponent {
constructor() {
super()
this.state = {
titleSize: 20
}
}
render() {
const { titleSize } = this.state
return (
<div>
<h2 style={{ color: 'red', fontSize: titleSize + 'px' }}>我是标题</h2>
<p style={{ color: 'blue', fontSize: '20px' }}>我是内容</p>
</div>
)
}
}
这个方案没有了全局的那两个缺点,他既可以用JS来控制,也不用担心作用域的问题,但是就是如果都在jsx中写样式的话,那后果可想而知
第三种:CSS Module写法
这种写法是基于Webpack的,Webpack允许CSS 文件中的类名和选择器局部作用于模块,防止全局污染,因此这种方案不仅react可以使用,vue也可以使用(只不过我们大都使用scoped写法),具体操作就是在我们声明的css文件中将名字改为xxx.module.css,然后就可以了。这种的写法的缺点就是我们无法通过JS来操控。
第四种:Less写法
这种写法跟全局css的写法差不多,只不过less写法多了一点东西,比如声明变量、样式嵌套等。不过如果我们如果需要再项目中开启less支持的话,我们需要配置一点东西(这里的脚手架使用的是create-react-app),然后我们可以借鉴antd design(4.x)中less的配置方案,安装craco。
yarn add @craco/craco
然后创建craco的配置文件craco.config.js,类似于vue中的vue.config.js,然后在配置文件中写下以下配置,我们的项目就可以使用less了。
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: { '@primary-color': '#1DA57A' },
javascriptEnabled: true,
},
},
},
},
],
};
第五种:CSS in JS方案
这种方案不同于前四种方案,是我认为比较完善的一种方案,他既能解决能够使用JS控制,也能有作用域,也不会使页面太过冗杂,当然了,这种方案是react社区提出的,需要安装对应的库(styled-components)。具体的使用如下:
import styled from "styled-components";
import * as variables from "./style/variables";
export const AppWrapper = styled.div``;
export const SectionWrapper = styled.div.attrs((props) => ({
color: props.color || "#000",
}))`
width: 200px;
height: 200px;
border: 1px solid red;
.title {
font-size: ${(props) => props.size}px;
color: ${(props) => props.color};
transition: font-size 0.5s;
&:hover {
color: ${variables.primaryColor};
font-size: ${variables.largeSize};
}
}
`;
这个方案不仅可以让我们拥有less般的体验,而且让我们像写js一样写CSS,这里使用的``是模板字符串的第二种使用方式,执行一个函数。然后上面的attr是接收传来的参数(我们在引用这个JS时,可以像组件一样传递参数,然后使用attr来接收),在写完这个并导出之后,我们需要替换原来的HTML标签为导出的这个,像下面这样:
import { AppWrapper, SectionWrapper } from "./style";
<AppWrapper>
<SectionWrapper size={size} color={color}>
<h2 className="title">我是标题</h2>
<p className="content">内容</p>
<button onClick={this.changeColor}>修改颜色</button>
</SectionWrapper>
</AppWrapper>
styled-components这个库的使用大致就是如此,具体可以查看官方文档(styled-components: Documentation)。