React中书写css代码
React
本身就是一个支持组件化的框架,但是React
并没有对css
处理好组件化。相较于Vue
,Vue
这个一块就处理的很好,css
放置在style
标签中,而且可以设置scope
作用域,防止样式覆盖,也可以设置css
预处理器。
在组件化开发中我们需要书写局部的css
,全局的css
,动态的css
(根据状态来设置css
)。
React
中书写css
就没有那么的方便,下面介绍一些在React
中css
的书写方式。
内联样式
官方推荐的一种写法。
export default class componentName extends Component {
render() {
return (
<div>
<h2 style={{ color: "red", fontSize: "20px" }}>你好</h2>
<h2 className='title'>世界</h2>
</div>
);
}
}
css
中短横线链接的属性需要转为小驼峰的形式来书写,以对象的形式书写css
样式,同时可以引入state
中的属性来动态引入属性。
当然缺点很明显,如果需要书写大量的代码,那这种方式一定不方便,没有代码提示等。另外一些样式也不能书写,伪元素等选择器是不能书写的。
普通的css引入
我们将css单独写在一个文件中,在引入到文件中。
import React, { Component } from "react";
import './index.css'
export default class componentName extends Component {
render() {
return (
<div>
<h2 style={{ color: "red", fontSize: "20px" }}>你好</h2>
<h2 className='title'>世界</h2>
</div>
);
}
}
但这样引入的css
没有组件之间的作用域,是作用在全局的,属于全局css
,会相互影响。所以适合写一些基本的全局样式。
css module 写法
该方法不是React
自带的方法,只要在类似webpack
配置打包环境下都可以使用。如果在其他项目中使用我们需要自己配置,配置webpack.config.js
中的属性modules:true
等。
React
脚手架已经配置了css modules
的配置。我们书写的.css/.less/.scss
都需要修改为.module.css/.module.less/.module.scss
。
引入方式,需要一个变量来接受,className
需要以{style.className}
形式来书写
import React, { Component } from "react";
import style from './index.module.css'
export default class componentName extends Component {
render() {
return (
<div>
<h2 style={{ color: "red", fontSize: "20px" }}>你好</h2>
<h2 className={style.title}>世界</h2>
</div>
);
}
}
这样就避免了作用域问题,渲染出来的className
如下:
当然缺陷也有,比如引入的类名不能是短横线连接,不方便修改属性。但这方法也是不错的css
书写方式。
CSS in JS
通过js
来增强React
中css
书写的一种方式。当然我们学些这个方式前先了解下ES6的一种语法,ES6标签模板字符串
我们使用该方法需要引入第三方库,这里推荐以下几个库:
- styled-components
- emotion
- glamorous
我们以styled-components
这个库来演示,这个库在社区中是很流行的。
安装方式:
//npm方式
npm install styled-components -S
//yarn方式
yarn add styled-components
该库本质上是调用函数来创建一个组件,组件会添加不会重复的class
。
该方式支持css
预处理器的嵌套写法,支持css
的各类写法。
基本用法:
import styled from "styled-components";
//创建一个组件
const TitleWrapper = styled.div`
color: yellow;
.title {
background-color: tomato;
&::after {
content: "---aaa";
}
}
`;
这个函数中根元素为div
,其中的样式只作用于该组件中
export default class CssInJS extends Component {
state = {color:'pink'}
render() {
return (
<div>
<TitleWrapper>
我是谁
<h3 className="title">hahah</h3>
</TitleWrapper>
</div>
);
}
}
渲染结果:
props,attr属性
props
可以穿透,直接作用在元素上
const InputWrapper = styled.input`
background-color: red;
`;
export default class CssInJS extends Component {
state = {color:'pink'}
render() {
return (
<div>
{/* 属性是可以穿透的,直接应用到标签上 */}
<InputWrapper type="password"></InputWrapper>
</div>
);
}
}
渲染结果:
另外获取props
需要通过${}
形式获取,其中定义一个函数,props
会作为函数的参数。
const InputWrapper = styled.input`
background-color: red;
padding: ${(props) => props.padding};
`;
export default class CssInJS extends Component {
state = { color: "pink" };
render() {
return (
<div>
<InputWrapper type="text" padding="20px"></InputWrapper>
</div>
);
}
}
attr
属性,为元素设置一些默认属性
const Input2Wrapper = styled.input.attrs({
placeholder: "zhangsan",
bColor: "red",//这种不存在的属性不能添加
'data-day':111
})`
background-color: #f2f2f2;
color: ${(props) => props.color};
`;
export default class CssInJS extends Component {
state = { color: "pink" };
render() {
return (
<div>
<Input2Wrapper color={this.state.color} />
</div>
);
}
}
渲染效果:
高级特性
支持样式继承
我们可以将另一个组件传入函数中来实现样式的继承
const SuperButton = styled.button`
padding: 8px 30px;
border-radius: 5px;
`;
const MyButton = styled(SuperButton)`
background-color: red;
color: #bfa;
`;
export default class CssInJS extends Component {
render() {
return (
<div>
<MyButton>按钮</MyButton>
</div>
);
}
}
渲染效果:
主题设置
import CIJ from "./cssInJS";
import { ThemeProvider } from "styled-components";
function App() {
return (
<div className="App">
你好
<ThemeProvider theme={{color:'#bcf', fontSize:'30px'}}>
<CIJ></CIJ>
</ThemeProvider>
</div>
);
}
export default App;
后代元素中获取theme
中的属性
const TitleWrapper = styled.div`
color: ${(props) => props.theme.color};
font-size: ${(props) => props.theme.fontSize};
.title {
background-color: tomato;
&::after {
content: "---aaa";
}
}
`;
动态添加className
在项目中我们需要为组件动态的添加一些css
类名,这在react
中只能自己实现。
React
没有为我们提供像Vue
中的一些模板语法(比如一些指令v-bind
等),我们可以借助一个第三方库classnames
来简化我们的工作量。
//npm
npm install classnames -S
//yarn
yarn add classnames
import React, { Component } from 'react'
import classNames from 'classnames';
export default class App extends Component {
constructor(props){
super(props);
this.state = {
isActive:true,
info:'info'
}
}
render() {
return (
<div>
<h2 className={'title ' + (this.state.isActive?'active':'')}>你好</h2>
<h2 className={classNames('foo', 'active')}>世界</h2>
<h2 className={classNames({'title':this.state.isActive}, 'foo')}>000</h2>
<h2 className={classNames({'title':this.state.isActive}, 'foo')}>111</h2>
<h2 className={classNames({'title':this.state.isActive}, 'foo', this.state.info)}>222</h2>
</div>
)
}
}
渲染结果: