穷尽一生,一事无成是常态,更是这个世界上99%的人真实写照
大家好,我是柒八九。
前言
就在前几天,写了一篇CSS 20大酷刑,然后看后台数据,反馈还是挺好的,看来大家还是对这个最熟悉的陌生人 ,有种食之无味,弃之可惜 的感觉。在上篇中,我们就说过,由于CSS
庞杂的体系和令人眼花缭乱的属性,总是让人望而却步 。但是,它也是我们翻身农奴做主人,势必要翻过的四座大山之一 CSS/Html/JavaScript/WebAsssembly
。(自认为,WebAssembly
也会成为一座我们需要逾越的大山,有关它的介绍,可以看我们之前写的浏览器第四种语言-WebAssembly)
而,今天我们讲点轻松的东西,内容有点少,可以在茶余饭后,当个配菜来品尝 。
在React
中,CSS模块(CSS Module
)只是一个.css
文件,类似于JavaScript中的局部变量 。它减少了React
样式的全局作用域。此外,它是一种通过生成一个随机字符串
作为className
名称并添加一个唯一的哈希来使每个className
都唯一的工具,从而防止和全局作用域冲突。我们可以使用CSS模块
来防止CSS类的命名冲突。只需将CSS模块
文件导入到我们的组件中,就可以在各种CSS
文件中使用相同的CSS类
。
任何CSS
文件都可以安全地更新,而无需担心会影响其他页面,因为它只具有局部作用域,只能影响使用了更改后的CSS模块
文件的其他组件。当使用CSS模块
在浏览器中呈现时,它会生成随机的CSS
类,只有在仔细检查页面时才可见。
你能所学到的知识点
- 前置知识点
- CSS模块的红与黑
- CSS模块使用语法
- 创建一下CSS模块
- 在React中使用 CSS 模块
- 全局 CSS
好了,天不早了,干点正事哇。
1. 前置知识点
前置知识点 ,只是做一个概念的介绍,不会做深度解释。因为,这些概念在下面文章中会有出现,为了让行文更加的顺畅,所以将本该在文内的概念解释放到前面来。如果大家对这些概念熟悉,可以直接忽略
CSS-in-JS
简介
CSS-in-JS
是一种前端开发方法,它将样式表达式嵌入到 JavaScript
中,以便更好地管理和组织样式。这种方法的主要思想是将组件的样式与组件本身紧密耦合在一起,以提高可维护性、可读性和复用性 。CSS-in-JS
有许多不同的库和工具,每个都有自己的语法和特性,但核心思想是相似的。
以下是 CSS-in-JS
的一些主要特点和优势:
-
组件化样式 :
CSS-in-JS
允许我们将样式与组件一起定义,将它们封装在一起。这使得代码更具可读性,因为我们可以在组件的定义中直接查看和理解样式。 -
动态样式 :与传统的
CSS
不同,CSS-in-JS
允许我们根据组件的状态或属性来动态生成样式。这使得样式更加灵活,能够根据应用的不同情况进行调整。 -
自动前缀 :许多
CSS-in-JS
库会自动添加浏览器前缀,以确保样式在不同浏览器中都能正常工作。 -
组件级别作用域 :样式是组件级别的,不会与其他组件的样式冲突,从而避免全局样式表的问题。
-
性能优化 :某些
CSS-in-JS
库会使用类似于样式提取 (style extraction
)的技术,将样式提取为单独的CSS
文件,以提高性能。 -
可维护性:将样式与组件紧密结合使得代码更易于维护,因为我们可以在同一个文件中查找组件的样式定义,而不必在多个文件之间跳转。
像比较常见的库有
由于它们的语法还有使用方式相差无几,所以我们就挑一个比较常见的库进行演示。如果想了解其它的使用方式,可以根据上面链接,直接访问其官网。
Styled Component
下面展示了如何使用 styled-components
创建一个简单的按钮组件:
首先,我们需要安装 styled-components
:
bash
npm install styled-components
然后,我们可以创建一个按钮组件:
jsx
// 导入 styled-components 库
import styled from 'styled-components';
// 创建一个样式化的按钮组件
const Button = styled.button`
background-color: #007bff;
color: #fff;
border: none;
padding: 10px 20px;
cursor: pointer;
&:hover {
background-color: #0056b3;
}
`;
// 在我们的应用中使用这个按钮组件
function App() {
return (
<div>
<h1>前端柒八九</h1>
<Button onClick={() => alert('Helllo, 骚年')}>关注走一波</Button>
</div>
);
}
export default App;
在上面的示例中,我们导入 styled-components
库,然后使用 styled.button
创建一个按钮组件。我们使用模板字符串定义了按钮的样式,包括背景颜色、文字颜色 等。&:hover
是一个伪类选择器
,用于定义按钮的鼠标悬停样式。
最后,在应用中使用这个按钮组件,就像使用普通的 React 组件一样。
2. CSS模块的红与黑
优点:
- 通过使用
CSS模块
,可以避免CSS类的命名空间冲突 。多个CSS文件可以包含相同的CSS类。 - 在
CSS模块
中,我们可以将类发送到多个组件。 - 使用
CSS模块
的一个关键优点是,我们可以放心地编辑任何CSS文件,而不必担心它会影响其他模块。 - 使用
CSS模块
创建可移植 和可重用的CSS文件。不再需要担心规则会影响其他组件的样式或选择器名称冲突。 - 尽管项目复杂,但
CSS模块
可以使我们的代码看起来整洁,以便其他开发人员可以阅读和理解它。
缺点:
- 在将样式集成到项目中时,必须将样式包含为带有
点号
或方括号
表示法的对象。 - 与
Styled Components
不同,CSS模块
不接受props
。
那么,为什么要使用CSS模块呢?
- 在使用
CSS模块
时,我们可以确保给定组件的每个样式都位于一个位置,并且仅适用于导入它的组件。 - 借助
CSS模块
和默认的局部作用域概念,可以避免全局作用域的问题。 - 在编写样式时,我们总是怕和别人起了相同的类名影响现有的业务,总是畏首畏尾,战战兢兢的编写自己的样式代码。
3. CSS模块使用语法
现在属于SPA
的天下,那在使用框架时候就绕不开,模块化构建工具(如Webpack
、vite
、Rspack
)来管理样式。
下面我们简单分别介绍一下,它们对CSS模块
的支持程度。
当我们安装create-React-app
时,React
会为我们处理一切;因此,我们目前不需要为Webpack
配置CSS模块
。
在使用CSS模块
时,不需要额外的代码或添加到CSS模块
的第三方代码。我们只需要将CSS文件的名称更改为[文件名].Modules.css
;我们可以用任何其他名称替代[文件名]
。在使用CSS模块
时,我们必须使用import
关键字将文件导入到特定组件中。在将CSS模块
集成到我们的React项目中时,我们必须指定类,就像在标准JavaScript中使用点符号或方括号语法访问对象的属性一样。
使用点符号表示法:
jsx
<div className={classes.parent_div}></div>
如果我们的CSS类包含连字符,应使用方括号表示法:
jsx
<div className={classes["parent-div"]}></div>
我们可以组合样式:
jsx
const buttonClasses = classes.myBtn + " " + classes.extra_classes;
这些是纯粹的普通JavaScript对象的基本概念。
Vite
天然支持CSS模块
Rspack
也天然支持CSS模块
4. 创建一下CSS模块
像Styled Component、Emotion和styled-jsx等CSS库现在都广泛使用。但是,我认为CSS模块
是会在未来大放异彩 ,特别是全局范围 和可重用性 ,这使得我们以后写样式时,不用如履薄冰。CSS模块
越来越广泛地用于在特定组件中本地描述样式并避免全局作用域。
让我们从一个简单的项目开始。我们将创建一个[文件名].module.css
文件。我们将导入我们的[文件名].module.css
的组件如下所示。
TypeScript
用户必须添加一个.d.ts
文件;在这种情况下,我们将创建[文件名].module.css.d.ts
"。
tsx
// [fileName].module.css.d.ts
export const styles: string;
export const someStyles: string;
export const moreStyles: string;
这个文件定义了一些CSS模块
中的样式类,可以在组件中使用。
[fileName].module.css
的内容如下所示:
css
.container {
width: 500px;
padding: 20px;
background-color: white;
box-shadow: 17px 18px 10px #767676;
text-align: center;
line-height: 3;
margin: 20px;
}
.border_radius {
border-radius: 40px;
}
.counter-title {
color: cornflowerblue;
font-family: cursive;
font-weight: bolder;
}
.container button {
background-color: cornflowerblue;
padding: 15px 20px;
border-radius: 10px;
color: white;
border: none;
outline: none;
}
要将CSS模块
的样式表导入到组件中,最好在[classes]
或[styles]
前缀下导入它。样式或类的前缀并不是强制性的,但我们将使用类以符合最佳实践。要使用样式,请确保路径包含./[fileName].module.css
对应的文件。
jsx
import classes from "./Styles.module.css";
5. 在React中使用 CSS 模块
在使用CSS 模块
时,可以将样式写在CSS
文件中,然后使用上面所示的点号
或方括号
表示法来引用导入的CSS模块
。在下面的代码中,我们演示了如何在React
组件中利用CSS Modules
。
函数组件
在React函数组件中,我们将使用CSS Modules
。下面的代码增加了计数器的值并使用useState
在将要创建的FunctionCounter.js
组件中。
jsx
import React, { useState } from "react";
import classes from "./Styles.module.css";
const FunctionCounter = () => {
const [counter, setCounter] = useState(0);
const handleClick = () => {
setCounter(counter + 2);
};
return (
<>
<div className={classes.container}>
<p className={classes["paragraph-text"]}>前端柒八九</p>
<h2 className={classes["counter-title"]}>{counter}</h2>
<button onClick={handleClick}>数字加2</button>
</div>
</>
);
};
export default FunctionCounter;
这个组件使用了从CSS模块
导入的样式类,并且在点击按钮时会增加计数器的值。这样,我们可以在React函数组件中利用CSS模块
来管理样式。
类组件
我们将看到一个使用CSS模块
的类组件。我们将创建一个名为ClassCounter.js
的Class组件。下面的代码会将计数值增加2。
jsx
import React from "react";
import classes from "./Styles.module.css";
class ClassCounter extends React.Component {
constructor() {
super();
this.state = { counter: 0 };
// 这个绑定是必要的,以使`this`在回调中正常工作
this.handleClick = this.handleClick.bind(this);
}
handleClick = () => {
this.setState({
counter: this.state.counter + 1,
});
};
render() {
return (
<div className={`${classes.container} ${classes.border_radius}`}>
<p className={classes["paragraph-text"]}>前端柒八九</p>
<h2 className={classes["counter-title"]}>{this.state.counter}</h2>
<button onClick={this.handleClick}>数字加1</button>
</div>
);
}
}
export default ClassCounter;
最后,让我们看一下App.js
组件。我们将在App.js
组件中导入FunctionCounter.js
和ClassCounter.js
组件。
jsx
import React from "react";
import ClassCounter from "./ClassCounter";
import FunctionCounter from "./FunctionCounter";
const App = () => {
return (
<div>
<FunctionCounter />
<br />
<ClassCounter />
</div>
);
};
export default App;
以下是我们的CSS模块
中的Class
和Function
组件的输出。
并且我们在浏览器中进行元素审查时,可以看到指定元素中的class
使用从CSS模块
获取的哈希值。
6. 全局 CSS
CSS模块
并不禁止使用全局CSS。我们可以使用与导入ES6相同的方法导入样式表。
jsx
import './App.css'
此外,我们可以使用关键字global
来更改类的范围,以防止CSS模块
修改它。
css
:global(.class) {
color:red;
}
:global .button {}
以下是上面代码的解释:
-
:global(.class)
:这是一个CSS Modules中的语法,:global
告诉CSS模块不要将此类名限制在模块范围内,而是将其视为全局CSS类名。这意味着任何地方都可以使用.class
类名,而不受模块化的限制。css/* 在CSS模块中 */ .class { color:red; }
在这里,
.class
类名的样式会在整个应用程序中全局生效。 -
:global .button
:这也是使用:global
将样式声明为全局的示例。.button
类名可以在整个应用程序中任何地方使用,不受模块化的限制。css/* 在CSS模块中 */ .button { /* 样式规则 */ }
在这里,
.button
类名的样式也会在整个应用程序中全局生效。
需要注意的是,:global
是一种逃逸机制 ,用于在CSS模块中定义全局样式。通常情况下,CSS Modules的目标是将样式局部化,以避免全局污染和冲突。但有些情况下,我们可能需要使用全局样式,这时可以使用:global
。
7. 多个 CSS模块混合使用
CSS模块不限制使用多个类;我们可以按照以下方式使用CSS模块
来添加多个类:
html
<div className={`${classes.container} ${classes.border_radius}`}></div>
function Footer( props) {
return (
<div className={styles.section}>
<div className={`${styles.description} ${styles.black}`}>
<p>CSS模块的使用说明</p>
</div>
</div>
);
}
8. 伪类选择器
伪类选择器
用于选择处于特定状态的元素。由于CSS模块
通过为我们的元素添加类来工作,因此添加伪类选择器非常简单。
jsx
// Button.module.css
.button:hover {background-color;: }
.button:disabled {color: #ddd}
.button:active {color: grau}
//============
import classes from "./Button.module.css";
import React, { Component } from "react";
export default class Text extends Component {
render() {
return <button className={classes.button}>关注我,给你一个不一样的技术分享</button>;
}
}
后记
分享是一种态度。
参考资料:
全文完,既然看到这里了,如果觉得不错,随手点个赞和"在看"吧。