react - css的模块化方案
本文介绍了三种现代CSS解决方案:CSS Modules、CSS原子化和CSS-in-JS。CSS Modules通过哈希类名实现样式隔离,在Vite中开箱即用;CSS原子化(如Tailwind和Unocss)将样式拆分为最小单元,具有代码体积小、维护性好等优势,但也存在HTML臃肿等问题;CSS-in-JS通过JS动态生成样式,可实现作用域隔离和动态样式,但存在性能损耗和调试困难等缺点。三种方案
文章目录
一、css modules
什么是 css modules
因为 React 没有 Vue 的Scoped,但是 React 又是 SPA(单页面应用),所以需要一种方式来解决 css 的样式冲突问题,也就是把每个组件的样式做成单独的作用域,实现样式隔离,而 css modules 就是一种解决方案,但是我们需要借助一些工具来实现;
比如 webpack,postcss,css-loader,vite 等。
如何在 Vite 中使用 css modules
css modules,可以配合各种 css 预处理去使用,例如 less,sass,stylus 等。
npm install less -D # 安装less 任选其一
npm install sass -D # 安装sass 任选其一
npm install stylus -D # 安装stylus 任选其一
在 Vite 中 css Modules 是开箱即用的,只需要把文件名设置为 xxx.module.[css|less|sass|stylus],就可以使用 css modules 了。
src/components/Button/index.module.scss
.button {
color: red;
}
src/components/Button/index.tsx
//使用方法,直接引入即可
import styles from "./index.module.scss";
export default function Button() {
return <button className={styles.button}>按钮</button>;
}
编译结果, 可以看到 button 类名被编译成了 button_pmkzx_6,这就是 css modules 的实现原理,通过在类名前添加一个唯一的哈希值,来实现样式隔离。
<button class="button_pmkzx_6">按钮</button>
二、CSS 原子化
什么是 CSS 原子化?
CSS 原子化(Atomic CSS)是一种将样式拆分为最小且独立单元的设计方法,其核心思想是每个 CSS 类只应用单一的样式属性,而不是组合样式。
例如,.bg-red只设置背景色为红色,.text-center只让文本居中。
原子化 CSS 的特点:
- 每个类名只控制一个样式属性
- 通过组合多个类实现复杂样式
- 减少冗余 CSS 代码,压缩文件大小
- 采用简单直观的命名规则,便于理解修改
如何使用 CSS 原子化
1. 使用 Tailwind CSS
Tailwind 是目前最流行的原子化 CSS 框架之一。安装使用非常简单:
npm install -D tailwindcss
然后创建配置文件tailwind.config.js,在其中可以自定义断点值、间距单位等:
// tailwind.config.js
module.exports = {
theme: {
screens: {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px"
},
spacing: {
1: "8px",
2: "12px",
3: "16px",
4: "24px",
5: "32px",
6: "48px"
}
}
};
使用示例:
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Button</button>
2. 使用 Unocss
Unocss 是另一款强大的原子化 CSS 引擎,相比 Tailwind 更加自由灵活。在 Vue3 + Vite + TS 项目中的配置方法:
安装依赖:
pnpm i -D unocss @unocss/preset-uno @unocss/preset-attributify @unocss/preset-icons
配置 vite.config.ts:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import Unocss from "unocss/vite";
import { presetUno, presetAttributify, presetIcons } from "unocss";
export default defineConfig({
plugins: [
vue(),
Unocss({
presets: [presetUno(), presetAttributify(), presetIcons()],
rules: [
[
"p-c",
{
position: "absolute",
top: "50%",
left: "50%",
transform: `translate(-50%, -50%)`
}
],
[/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })]
]
})
]
});
使用示例:
<div class="text-25px text-#ff6700 bg-#ccc">你好Unocss</div>
<div class="i-logos-atomic-icon w-50px h-50px"></div>
原子化 CSS vs SCSS:优势对比
1. 代码体积显著减少
Facebook 重构后采用原子化 CSS,主页 CSS 体积减少了 80%。这是因为原子化 CSS 通过高度复用样式规则,避免了传统 CSS 中的大量重复代码。
2. 更少的样式冲突
原子化 CSS 使用最简单的类选择器,CSS 权重问题几乎不存在。而在 SCSS 中,嵌套选择器可能导致权重问题,需要谨慎管理。
3. 更好的可维护性
当需要修改样式时,原子化 CSS 允许直接修改 HTML 中的类名,而不是去查找和修改 CSS 文件。这种"紧密耦合"在现代前端框架中被证明是高效的。
4. 更快的开发速度
有了完善的原子类库和编辑器智能提示,开发者可以快速组合出所需样式,无需反复在 HTML 和 CSS 文件间切换。而 SCSS 虽然提供了变量、混合等特性,但仍需要手动编写样式规则。
5. 更优的缓存策略
原子化 CSS 一旦准备好,将不会有太大变化或增长,可以更有效地缓存它。而 SCSS 生成的 CSS 会随着项目增长而不断变化。
6. 更简单的删除无用代码
删除功能时,原子化 CSS 确保相关样式也同时被删掉,因为样式直接写在 HTML 中。而 SCSS 中可能存在残留的无用样式规则。
原子化 CSS 的局限性
尽管有诸多优势,原子化 CSS 也存在一些挑战:
-
HTML 臃肿:复杂的元素可能需要大量类名,使 HTML 变得冗长。不过类名中的高冗余使得 gzip 可以很好压缩。
-
学习曲线:需要学习一套新的命名约定,初期可能影响开发效率。
-
一次性样式处理:当需要一些特殊样式而原子库未提供时,处理起来不太方便。
-
伪类支持有限:需要用到伪类的地方通常需要结合传统写法。
三、css-in-js(不推荐使用)
css-in-js 是将 CSS 代码 跟 JS 代码 混合在一起,通过 JS 来动态的生成 CSS 样式,但是这样的话与我们的认知是背道而驰的,正常应该是CSS JS HTML分离的,但是由于 CSS 缺乏作用域,所以形成了 css-in-js 这种写法,注它并不是一种技术,而是一种思想。
优缺点
优点: 可以让 CSS 拥有独立的作用域,阻止 CSS 泄露到组件外部,防止冲突。可以动态的生成 CSS 样式,根据组件的状态来动态的生成 CSS 样式。 css-in-js 可以方便地实现主题切换功能,只需更改主题变量即可改变整个应用的样式。
缺点: css-in-js 是基于运行时,所以会损耗一些性能(电脑性能高可以忽略) 调试困难,css-in-js 的样式难以调试,因为它们是动态生成的,而不是在 CSS 文件中定义的。
更多推荐


所有评论(0)