下面举例默认支持less和sass。
index.less(外联样式文件)
.out-css{
.text{
font-size: 20px;
color: red;
}
}
OutCss.js(react组件)
import React from 'react';
// 引入外联样式,一经加载将全局有效,所以类名在命名的时候要特别注意,避免全局污染
import './index.less';
const OutCss = () => (
// 外联样式一般都使用组件名作为最外层的类名,这样能防止类名全局污染
<div className="out-css">
<p className="text">引入外联样式</p>
</div>
);
export default OutCss;
优点:方便、简洁
缺点:样式一经加载将全局生效,类名相同时样式之间会互相影响
如何解决:一般使用组件名作为最外层的类名,这样能防止类名全局污染
import React, { useState } from 'react';
const Com = () => {
const [isShow, setIsShow] = useState(true);
return (
<div>
<p
// 编辑器有提示,对象中的样式写法要使用驼峰式写法
style={{
display: isShow ? 'block' : 'none', // 推荐这种情况下使用内联样式
backgroundColor: 'red', // 这种情况建议使用类名来控制样式(引入外联样式)
}}
>
内联样式(直接在style中写入对象)
</p>
</div>
);
};
export default Com;
优点:
内联样式, 样式之间不会有冲突
可以动态获取当前组件的state状态
缺点:
写法上都需要使用驼峰标识
某些样式编辑器没有提示
大量使用这种样式, 代码会混乱
某些样式无法编写(比如伪类/伪元素)
性能上不太好,组件每次渲染都会创建新的对象
import React, { useState } from 'react';
// 编辑器无提示,对象中的写法和css一样
const wrapCss = {
'font-weight': 'bold',
color: 'blue',
'background-color': '#999', // 也可以这样写: backgroundColor: '#999'
};
const Com = () => {
return (
<div>
<p style={wrapCss}>
内联样式(引入外部变量,组件重新渲染时不会每次都创建新的对象,性能较上面直接在style中写入对象的好一点)
</p>
</div>
);
};
export default Com;
优点:
内联样式, 样式之间不会有冲突
性能上比直接在style中写入对象的好一点
缺点:
写样式时编辑器没有提示
大量使用这种样式, 代码会混乱
某些样式无法编写(比如伪类/伪元素)
这种方式是webpack的方案,需要配置webpack配置文件中modules:true,具体如何配置可以百度下。
如果使用create-react-app来开发项目,那么默认是支持了的。
test.module.less(模块化样式文件)
// 引入模块化样式的类名不会全局污染,所以可以根据当前引入的组件定义合适的类名即可使用
.wrap{
font-size: 20px;
color: red;
// 如果类名使用有冲突的话,就根据样式优先级来显示
.span-test{
font-weight: bold;
color: blue;
}
}
// 举例类名有冲突的情况
.span-test{
font-weight: bold;
color: #666;
}
ModuleCss.js(react组件)
import React from 'react';
// 注意这里的引入方式和模块化样式文件的命名为.module.less / .module.scss / .module.css结尾
// css样式仅在当前引入的组件生效
import styles from './test.module.less';
const Com = () => (
// 无中划线的类名这样使用
<div className={styles.wrap}>
引入外联模块化样式
{/* 有中划线的类名这样使用 */}
<span className={styles['span-test']}>span</span>
</div>
);
export default Com;
优点:
将css文件作为一个模块引入,这个模块中的所有css,只作用于当前组件。不会影响当前组件的后代组件。样式之间不会有冲突
缺点:
所有的 className 都必须使用 {style.className} 的形式来编写
不方便动态来修改某些样式,依然需要使用内联样式的方式
CSS-in-JS, 是指一种模式,其中CSS由 JavaScript生成而不是在外部文件中定义
此功能并不是 React 的一部分,而是由第三方库提供,例如:
styled-components
emotion
glamorous
下面主要看看styled-components的基本使用。
本质是通过函数的调用,最终创建出一个组件,所以变量名首字母要大写:
这个组件会被自动添加上一个不重复的class
styled-components会给该class添加相关的样式
在vscode中想要styled-components语法提示高亮,可以安装vscode-styled-components 插件。
import React from 'react';
import { Button } from 'antd';
// 需要使用 npm 进行安装 styled-components
import styled from 'styled-components';
// 使用其他ui组件时的写法
const MyButton = styled(Button)`
&.ant-btn{
color: red;
}
`;
// 使用原生html标签时的写法
const MyDiv = styled.div`
p{
span{
font-size: 24px;
// 如果想要使用props可以这样写
width: ${(props) => `${props.width}px`};
}
}
`;
const Com = (props) => (
<div>
CSS-in-JS(注意:定义好之后它也是一个组件,所以变量名首字母要大写)
<br />
{/* css样式不会冲突,仅在使用的当前组件生效 */}
<MyButton>按钮</MyButton>
<MyDiv>
<p><span>我的p标签</span></p>
</MyDiv>
</div>
);
export default Com;
styled.js (提取出去的样式组件)
import { Button } from 'antd';
// 需要使用 npm 进行安装 styled-components
import styled from 'styled-components';
// 使用其他ui组件时的写法
export const MyButton = styled(Button)`
&.ant-btn{
color: red;
}
`;
// 使用原生html标签时的写法
export const MyDiv = styled.div`
p{
span{
font-size: 24px;
color: blue;
}
}
`;
StyledComponents.js(react组件)
import React from 'react';
// 导入样式组件
import {
MyButton,
MyDiv,
} from './styled';
const Com = () => (
<div>
CSS-in-JS(注意:定义好之后它也是一个组件,所以变量名首字母要大写)
<br />
{/* css样式不会冲突,仅在使用的当前组件生效 */}
<MyButton>按钮</MyButton>
<MyDiv>
<p><span>我的p标签</span></p>
</MyDiv>
</div>
);
export default Com;
优点:
通过css in js 这种方法,可以满足大部分场景的应用,可以类似于预处理器一样样式嵌套、定义、修改状态等
缺点:
审查组件样式时不太直观,书写有点麻烦
通过上面5种样式的引入,可以看到:
至于使用react时用哪种方案引入css,可以根据各自情况选择合适的方案。
参考文章:
说说React中引入Css的方式有哪几种?区别?