React中引入样式的5种方式(代码举例 & 优缺点)

前言:

下面举例默认支持less和sass。

1、引入外联样式

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;

优点:方便、简洁

缺点:样式一经加载将全局生效,类名相同时样式之间会互相影响

如何解决:一般使用组件名作为最外层的类名,这样能防止类名全局污染

2、内联样式

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状态

缺点
写法上都需要使用驼峰标识
某些样式编辑器没有提示
大量使用这种样式, 代码会混乱
某些样式无法编写(比如伪类/伪元素)
性能上不太好,组件每次渲染都会创建新的对象

3、声明式内联样式

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中写入对象的好一点

缺点
写样式时编辑器没有提示
大量使用这种样式, 代码会混乱
某些样式无法编写(比如伪类/伪元素)

4、CSS Modules模块化

这种方式是webpack的方案,需要配置webpack配置文件中modules:true,具体如何配置可以百度下。
React中引入样式的5种方式(代码举例 & 优缺点)_第1张图片

如果使用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} 的形式来编写
不方便动态来修改某些样式,依然需要使用内联样式的方式

5、CSS-in-JS模式(Styled-component)

CSS-in-JS, 是指一种模式,其中CSS由 JavaScript生成而不是在外部文件中定义

此功能并不是 React 的一部分,而是由第三方库提供,例如:

styled-components
emotion
glamorous

下面主要看看styled-components的基本使用。

本质是通过函数的调用,最终创建出一个组件,所以变量名首字母要大写

这个组件会被自动添加上一个不重复的class
styled-components会给该class添加相关的样式

在vscode中想要styled-components语法提示高亮,可以安装vscode-styled-components 插件。

5.1、直接在react组件中定义并使用
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;

5.2、提取出styled-components样式

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种样式的引入,可以看到:

  • 在组件内直接使用内联样式编写方便,容易能够根据状态修改样式属性,但是大量的编写容易导致代码混乱,性能上也不比使用外联样式的好
  • 组件中引入 .css 文件(使用外联样式)符合我们日常的编写习惯,但是作用域是全局的,样式之间会层叠(在定义类名的时候需要严谨些)
  • 引入.module.css 文件能够解决局部作用域问题,但是不方便动态修改样式,需要使用内联的方式进行样式的编写
  • 通过css in js 这种方法,可以满足大部分场景的应用,可以类似于预处理器一样样式嵌套、定义、修改状态等。就是有点不符合日常编写习惯。

至于使用react时用哪种方案引入css,可以根据各自情况选择合适的方案。


参考文章:

说说React中引入Css的方式有哪几种?区别?

你可能感兴趣的:(React,react,css)