Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >React 进阶 - 模块化 CSS

React 进阶 - 模块化 CSS

作者头像
Cellinlab
发布于 2023-05-17 12:49:44
发布于 2023-05-17 12:49:44
2K00
代码可运行
举报
文章被收录于专栏:Cellinlab's BlogCellinlab's Blog
运行总次数:0
代码可运行

# 模块化 CSS 的作用

随着 React 项目日益复杂化、繁重化,React 中 css 面临很多问题,比如样式类名全局污染、命名混乱、样式覆盖等。这时, css 模块化就显得格外重要。

css 模块化的几个重要作用:

  • 防止全局污染,样式被覆盖
    • 如果不规范 css 的话,这种情况在实际开发中会变得更加棘手,有时候甚至不得不用 !important 或者 行内样式 来解决
    • Web Components 标准中的 Shadow DOM 能彻底解决这个问题,但它的做法有点极端,样式彻底局部化,造成外部无法重写样式,损失了灵活性
  • 解决命名混乱
    • 没有 css 模块化和统一的规范,会使得多人开发,没有一个规范
  • 减少 css 代码冗余,体积庞大
    • React 中各个组件是独立的,所以导致引入的 css 文件也是相互独立的,比如在两个 css 中,有很多相似的样式代码,如果没有用到 css 模块化,构建打包上线的时候全部打包在一起,那么无疑会增加项目的体积

React 使用 css 模块化的思路:

  • css module ,依赖于 webpack 构建和 css-loader 等 loader 处理,将 css 交给 js 来动态加载
  • 直接放弃 css ,css in js 用 js 对象方式写 css ,然后作为 style 方式赋予给 React 组件的 DOM 元素,这种写法将不需要 .css .less .scss 等文件,取而代之的是每一个组件都有一个写对应样式的 js 文件

# CSS Modules

css Modules ,使得项目中可以像加载 js 模块一样加载 css ,本质上通过一定自定义的命名规则生成唯一性的 css 类名,从根本上解决 css 全局污染,样式覆盖的问题。对于 css modules 的配置,推荐使用 css-loader,它对 CSS Modules 的支持最好,而且很容易使用。

css-loader 配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  test: /\.css$/,
  use: [
    'css-loader?modules'
  ]
}

css 文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.title {
  color: red;
}

js 文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import style from './index.css'

const App = () => {
  return (
    <div className={style.title}>Hello World</div>
  )
}

# 自定义命名规则

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  test: /\.css$/,
  use: [
    {
      loader: 'css-loader',
      options: {
        modules: {
          localIdentName: '[path][name]__[local]--[hash:base64:5]'
        }
      }
    }
  ]
}

  • [path][name]__[local] -> 开发环境,便于调试,可以直接找到此类名对应的文件
  • [hash:base64:5] -> 生产环境,便于生产环境压缩类名

# 全局变量

一旦经过 css modules 处理的 css 文件类名 ,再引用的时候就已经无效了。因为声明的类名,比如如上的 .text 已经被处理成了哈希形式。

那么怎么样快速引用声明好的全局类名呢?CSS Modules 允许使用 :global(.className) 的语法,声明一个全局类名。凡是这样声明的 class ,都不会被编译成哈希字符串。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.title {
  color: red;
}
:global(.title_bg) {
  background-color: pink;
}

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import style from './index.css'

const App = () => {
  return (
    <div className={`${style.title} title_bg`}>Hello World</div>
  )
}

CSS Modules 还提供一种显式的局部作用域语法: local(.title) 等同于 .title

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.title {
  color: red;
}

/* 等同于 */
:local(.title) {
  color: red;
}

# 组合样式

CSS Modules 提供了一种 composes 组合方式,实现对样式的复用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.base {
  color: blue;
}
.title {
  composes: base; /* 继承 base 样式 */
  font-size: 20px;
}

composes 可以将多个 class 类名添加到元素中。composes 还有一个更灵活的方法,支持动态引入别的模块下的类名。

style1.css:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.base {
  color: red;
}

style2.css:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.title {
  composes: base from './style1.css';
  font-size: 20px;
}

# 配置 less 和 sass

less webpack 配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  test: /\.less$/,
  use: [
    {
      loader: 'css-loader',
      options: {
        modules: {
          localIdentName: '[path][name---[local]---[hash:base64:5]'
        }
      }
    },
    'less-loader'
  ]
}

  • index.less:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.text {
  color: blue;
  background-color: pink;
}

  • index.js:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import style from './index.less'

const App = () => {
  return (
    <div className={style.text}>Hello World</div>
  )
}

# 组合方案

正常情况下,React 项目可能在使用 css 处理样式之外,还会使用 scss 或者 less 预处理。

  • 可以约定对于全局样式或者是公共组件样式,可以用 .css 文件 ,不需要做 CSS Modules 处理,这样就不需要写 :global 等繁琐语法
  • 对于项目中开发的页面和业务组件,统一用 scss 或者 less 等做 CSS Module,也就是 css 全局样式 + less / scss CSS Modules 方案

这样就会让 React 项目更加灵活的处理 CSS 模块化。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react';

import style from './index.less';

export default () => {
  return <div>
    <button className='search-btn'>Search</button>
    <div className={style.text}>Less + CSS Modules</div>
  </div>
}

# 动态添加 class

CSS Modules 可以配合 classNames 库 实现更灵活的动态添加类名。

index.less

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.base {}
.dark {
  background-color: #000;
  color: #fff;
}
.light {
  background-color: #fff;
  color: #000;
}

index.jsx

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cx from 'classnames';

import style from './index.less';

export default function Index() {
  const [theme, setTheme] = useState('dark');
  return <div>
    <button
      className={cx(style.base, style[theme])}
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
    >
      Change Theme
    </button>
  </div>;
}

# CSS Modules 优点及注意事项

  • 优点
    • CSS Modules 的类名都有自己的私有域的,可以避免类名重复/覆盖,全局污染问题
    • 引入 css 更加灵活,css 模块之间可以互相组合
    • class 类名生成规则配置灵活,方便压缩 class 名
  • 注意事项
    • 仅用 class 类名定义 css ,不使用其他选择器
    • 不要嵌套 css .a{ .b{} } 或者重叠 css .a .b {}

# CSS IN JS

# 基础使用

CSS IN JS 相比 CSS Modules 更加简单, CSS IN JS 放弃 css ,用 js 对象形式直接写 style 。

index.jsx

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react';
import Style from './style';

export default function Index() {
  return <div style={Style.boxStyle}>
    <span style={Style.textStyle}>CSS in JS</span>
  </div>;
}

style.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const boxStyle = {
  backgroundColor: '#000',
};

const textStyle = {
  color: '#fff',
};

export default {
  boxStyle,
  textStyle,
};

# 灵活运用

由于 CSS IN JS 本质上就是运用 js 中对象形式保存样式, 所以 js 对象的操作方法都可以灵活的用在 CSS IN JS 上。

拓展运算符实现样式继承

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const baseStyle = {
  color: '#fff',
  fontSize: '20px',
};
const containerStyle = {
  ...baseStyle,
  backgroundColor: '#000',
};

动态添加样式变得更加灵活

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const dark = {
  backgroundColor: '#000',
};
const light = {
  backgroundColor: '#fff',
};

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react';
import Style from './style';

const Index = () => {
  return <div style={theme === 'light' ? Style.dark : Style.light }>
    CSS in JS
  </div>;
}

# styled-components 库

CSS IN JS 也可以由一些第三方库支持,如 styled-components, 可以把写好的 css 样式注入到组件中,项目中应用的已经是含有样式的组件。

基础用法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react';
import styled from 'styled-components';

/* 给 button 标签添加样式,形成 Button React 组件 */
const Button = styled.button`
  background: #6a8bad;
  color: #fff;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
`;
export default function Index() {
  return <Button>Styled Components</Button>;
}

基于 props 动态添加样式

  • 通过给生成的组件添加 props 属性 ,来动态添加样式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react';
import styled from 'styled-components';

const Button = styled.button`
  background: #6a8bad;
  color: #fff;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
  /* 通过 props 来动态添加样式 */
  ${props => props.primary && `
    background: #fff;
    color: #6a8bad;
  `}
`;

export default function Index() {
  return <div>
    <Button>Styled Components</Button>
    <Button primary>Styled Components</Button>
  </div>;
}

继承样式

  • 可以通过继承方式来达到样式的复用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from 'react';
import styled from 'styled-components';

const Button = styled.button`
  background: #6a8bad;
  color: #fff;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
`;

const PrimaryButton = styled(Button)`
  background: #fff;
  color: #6a8bad;
`;

export default function Index() {
  return <div>
    <Button>Styled Components</Button>
    <PrimaryButton>Styled Components</PrimaryButton>
  </div>;
}

# CSS IN JS 特点及注意事项

  • 特点
    • CSS IN JS 本质上放弃了 css ,变成了 css in line 形式,所以根本上解决了全局污染,样式混乱等问题
    • 运用起来灵活,可以运用 js 特性,更灵活地实现样式继承,动态添加样式等场景
    • 由于编译器对 js 模块化支持度更高,使得可以在项目中更快地找到 style.js 样式文件,以及快捷引入文件中的样式常量
    • 无须 webpack 额外配置 css,less 等文件类型
  • 注意事项
    • 虽然运用灵活,但是写样式不如 css 灵活,由于样式用 js 写,所以无法像 css 写样式那样可以支持语法高亮,样式自动补全等
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/9/15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【React】:CSS 模块化
以下是 CSS Guidelines 中的一个示例,这个示例展示了一个问题:除了写这段代码的人,没有人知道这段代码是干什么的。
WEBJ2EE
2020/07/14
1.3K0
【React】:CSS 模块化
CSS Modules VS. styled-components,哪个才是解决 CSS 不足之处的更好方案?
CSS 是一门标记语言,用于元素布局及样式定义。它存在很多问题,例如书写效率和维护性低;缺乏模块机制、变量、函数等概念;容易出现全局样式污染和样式冲突等。目前前端社区存在很多解决上述问题的方案,主要包括 CSS Module以及 styled-components💅(CSS-in-JS 的代表)。 styled-components 在我的日常开发中用得很多,并且用得非常顺手。它的 CSS-in-JS 思想以及通过 props 来动态更改样式跟 React 的开发理念一脉相承,并且还基于 React Con
玖柒的小窝
2021/10/31
8K1
CSS Modules VS. styled-components,哪个才是解决 CSS 不足之处的更好方案?
如何在 React 中优雅的写 CSS
看目录结构清晰明了,由于“ CSS 文件分离 != CSS 作用域隔离”这样的机制,如果我们不通过一些工具或规范来解决 CSS 的作用域污染问题,会产生非预期的页面样式渲染结果。
政采云前端团队
2019/12/20
4.1K0
如何在 React 中优雅的写 CSS
react的css
与传统 html 标签类属性不同,react 中 class 必须编写为 className,比如
愧怍
2022/12/27
1.6K0
react的css
React基础(10)-React中编写样式CSS(styled-components)
React是一个构建用户界面的js库,从UI=render()这个等式中就很好的映射了这一点,UI的显示取决于等式右边的render函数的返回值.
itclanCoder
2020/10/17
4.4K0
在React项目中使用CSS Module
就在前几天,写了一篇CSS 20大酷刑,然后看后台数据,反馈还是挺好的,看来大家还是对这个「最熟悉的陌生人」,有种「食之无味,弃之可惜」的感觉。在上篇中,我们就说过,由于CSS庞杂的体系和令人眼花缭乱的属性,总是让人「望而却步」。但是,它也是我们翻身农奴做主人,势必要翻过的四座大山之一 CSS/Html/JavaScript/WebAsssembly。(自认为,WebAssembly也会成为一座我们需要逾越的大山,有关它的介绍,可以看我们之前写的浏览器第四种语言-WebAssembly)
前端柒八九
2023/09/10
1.5K0
在React项目中使用CSS Module
CSS Modules与Styled Components:提升CSS可维护性
CSS Modules和Styled Components都是现代Web开发中用于提升CSS可维护性的解决方案,它们通过不同的方式解决了传统CSS的一些问题,如样式冲突、命名约定和全局作用域。
天涯学馆
2024/08/17
1100
css模块化及CSS Modules使用详解
什么是css模块化? 为了理解css模块化思想,我们首先了解下,什么是模块化,在百度百科上的解释是,在系统的结构中,模块是可组合、分解和更换的单元。模块化是一种处理复杂系统分解成为更好的可管理模块的方式。它可以通过在不同组件设定不同的功能,把一个问题分解成多个小的独立、互相作用的组件,来处理复杂、大型的软件。看完模块化,是不是有种拼图的即视感,可以把大图分成各个小图,然后把小图拼成大图,分与合的艺术感。那么css模块化思想,也就是在css编写环境中,用上模块化的思想,把一个大的项目,分解成独立的组件,不同的
xiangzhihong
2018/02/05
6.9K0
React 中使用CSS
注意事项: 在正常的css中,比如background-color,box-sizing等属性,在style对象div1中的属性中,必须转换成驼峰法,backgroundColor,boxSizing。而没有连字符的属性,如margin,width等,则在style对象中不变。
grain先森
2019/03/28
1.4K0
7. 精读《请停止 css-in-js 的行为》
styled-components 利用 ES6 的 tagged template 语法创建 react 纯样式组件。消除了人肉在 dom 和 css 之间做映射和切换的痛苦,并且有大部分编辑器插件的大力支持(语法高亮等)。此外,styled-components 在 ReactNaive 中尤其适用。
黄子毅
2022/03/14
2K0
7. 精读《请停止 css-in-js 的行为》
React组件设计实践总结03 - 样式的管理
CSS 是前端开发的重要组成部分,但是它并不完美,本文主要探讨 React 样式管理方面的一些解决方案,目的是实现样式的高度可定制化, 让大型项目的样式代码更容易维护.
_sx_
2019/08/07
7.2K0
React组件设计实践总结03 - 样式的管理
CSS Modules入门教程
或者可以这么说,CSS Modules为我们解决了什么痛点。针对以往我写网页样式的经验,具体来说可以归纳为以下几点:
糊糊糊糊糊了
2018/09/28
2.6K0
CSS Modules入门教程
CSS in JS的好与坏
CSS-in-JS是一种技术(technique),而不是一个具体的库实现(library)。简单来说CSS-in-JS就是将应用的CSS样式写在JavaScript文件里面,而不是独立为一些 .css, .scss或者 less之类的文件,这样你就可以在CSS中使用一些属于JS的诸如模块声明,变量定义,函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义。值得一提的是,虽然CSS-in-JS不是一种很新的技术,可是它在国内普及度好像并不是很高,它当初的出现是因为一些 component-based的Web框架(例如React,Vue和Angular)的逐渐流行,使得开发者也想将组件的CSS样式也一块封装到组件中去以解决原生CSS写法的一系列问题。还有就是CSS-in-JS在React社区的热度是最高的,这是因为React本身不会管用户怎么去为组件定义样式的问题,而Vue和Angular都有属于框架自己的一套定义样式的方案。
进击的大葱
2022/08/22
2.4K0
CSS in JS的好与坏
CSS模块化的演进
| 导语 CSS 做为 Web 技术的基石,从一开始就展示出了巨大的潜力。它的入门非常简单,你只需为元素定义好样式属性和值。然而 CSS 特性随着规范的升级越来越丰富,前端业务复杂性的增加也使得工程愈加庞大。在大型 Web 应用里面,CSS 的组织是一件复杂和凌乱的事情,你更改页面上任意一个元素的一行CSS样式都有可能影响到其他页面上的元素。 由于 CSS 本身并不编程特性,因此在演变过程中出现了很多优秀的编程思想,本文会带领大家探讨 CSS 模块化的演变历程。 CSS 预处理器 CSS 预处理器是什
腾讯NEXT学位
2018/08/29
1.7K0
CSS模块化的演进
react进阶用法完全指南
React调用回调函数,正确设置this指向的三种方法 通过bind this.increment = this.increment.bind(this); 通过箭头函数 <button onClick={this.multi}>点我*10</button> multi = () => { this.setState({ count: this.state.count * 10 }) } 箭头函数包裹 <button onClick={() => {this.muti2(
xiaofeng123aa
2022/09/26
6K0
styled-components不完全手册
大家好,我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder
前端柒八九
2024/03/25
1140
styled-components不完全手册
CSS Modules 学习
CSS Modules 的用法很简单,不过现阶段还需要 webpack 的支持。CSS Modules 的功能非常少,它一共就干了两件事:局部作用域和模块依赖。
李振
2021/11/26
4940
CSS Modules 学习
手写 css-modules 来深入理解它的原理
我们知道,浏览器里的 JS 之前没有模块的概念,都是通过不同的全局变量(命名空间)来隔离,后来出现了 AMD、CMD、CommonJS、ESM 等规范。
神说要有光zxg
2022/06/06
5420
手写 css-modules 来深入理解它的原理
理解CSS模块化
在瞬息万变的前端开发世界中,很难找到一个真正有意义的概念,并且将其清晰明了的向广大人民群众普及。
疯狂的技术宅
2019/03/28
6310
react css组织的另一种选择styled-components
本文介绍了如何使用 styled-components 库来编写具有良好视觉效果和可维护性的 CSS 组件,同时介绍了该库的一些特性。
IMWeb前端团队
2018/01/08
9330
相关推荐
【React】:CSS 模块化
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验