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)。