- 作者:老汪软件技巧
- 发表时间:2024-10-09 10:01
- 浏览量:
hello,同学们(早/中/晚)上好啊!
大家有样式污染,样式穿透的烦恼吗。
A组件的一个css样式影响了B组件的另一个同名样式。组件组件的某个样式A意外的作用到了子孙组件的某个同名css上。
一般都会有一套自己的命名规则,比如在一个盒子布局里面有些同学固定就是.leftBox,.rightBox,.container。但是这样在一个很大体量的项目里使用一套命名规则,又会加重样式污染的概率。那也没办法,对于开发人员来说,给css命名是一件痛苦的事情。实在是憋不出那么多名字。
对于复杂或者庞大的项目来说,这些问题都已经见怪不怪了。过去接手过一个维护了很多年又比较大的远古项目,那里面的样式穿透,嘶~
为什么会有样式穿透的问题
这个得从咱们的项目对于css的引用规则说起。大家都知道,react组件的代码是不可以被浏览器识别的,我们编写react的代码可以在浏览器中被映射出来,是因为webpack把它编译成了一段浏览器可以识别的html。
我们简单的说webpack编译,这里就不展开,否则一个篇幅下来恐怕要没完没了了。
大概是这么个情况
举个,下图是一个react项目
他会被编译成如下这段浏览器可以识别的html代码。
接下来咱们说说为什么会有样式穿透。
假设组件A引入了一个css文件,该css文件里有一个类名为test,内容是color:red
组件B没有引入任何css文件,但是,组件B内存在一个一个名为test的类。
请问:组件B中这个名为test的类也会有color:red这个css效果吗
会有
被组件引用的css会被直接挂载到head标签上,其他的jsx代码都会被一起编译到body里。这也就意味着,这个名为.test的类不论是被jsx里面的哪个组件引用的,都会作用到其他的任何一个组件中去。 所以,上图最后一行红字虽然是其他组件,但依然收到了其他组件css的影响(字体变红了)
有什么办法可以避免样式穿透和污染的问题?
有几种方案。
1.自己制定一套命名规则(不推荐,太痛苦)
2.使用less,然后给每一个组件一个父类,以后的css都写在这个父类下面,利用·less的作用域解决不同兄弟组件之间的冲突。(不推荐,只能解决污染不能解决穿透)。
3.使用css modules(推荐,交给机器解决命名冲突问题,对于研发来说完全无感不需要考虑其他)
什么是css modules
CSS Modules是一种将CSS与模块系统结合的技术,旨在解决传统CSS管理中的全局样式污染和可维护性问题**。它通过为每个CSS样式定义分配一个唯一的模块名,实现了CSS样式的局部作用域和模块隔离。具体来说,当使用CSS Modules时,可以将CSS文件视为一个模块,其中的样式被视为模块的内部属性。在代码中引入CSS文件时,会生成一个与模块对应的对象,其中包含了所有的样式定义。这些样式定义只能在当前模块内部使用,不会影响到其他模块12。
CSS Modules的主要特点包括:
使用CSS Modules可以解决一些常见问题:
css_modules是如何解决样式冲突的。
css_modules会在jsx被编译成html的过程中修改项目的css名称,让css加上一段唯一的随机字符串。让css和html的类通过这个唯一字符串形成唯一的映射关系。em....口述可能不能很好的表达,我们来个图看看。
下图:两个组件的类依然都叫test,这次不一样的是,通过css模块化修改了一下映射到浏览器上面之后的类名。
这样就不会冲突了。
如何配置和使用css_module
每种框架对于配置css的具体细节并不一样,大家要配置的时候建议问chatGPT。
这里我们以vite框架来演示下less的配置和使用过程。
如何配置 css_modules
打开vite.config.ts 在css这个模块下按如下配置。
css: {
modules: {
// 你可以在这里添加自定义配置,例如全局的 CSS Modules 类名生成器
generateScopedName: '[name]__[local]__[hash:base64:5]'
}
}
如何使用css_modules修改 [xxx].css 为 [xxx ].module.css在需要映入css的文件内通过模块的形式引入,不要直接引入。例如 import "./index.css" => import styles from "index.css"最后用映入的模块进行【styles.calssName】。例如 className={styles.test}
看不懂没事,有图⬇️。
PS:index.module.css文件内的css不需要做任何改变,该咋写咋写。
最后
PS: 在老项目里面追加css_modules功能是完全没有问题的,不会影响其他普通的css。