likes
comments
collection
share

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

作者站长头像
站长
· 阅读数 30

hello,同学们(早/中/晚)上好啊!

大家有样式污染,样式穿透的烦恼吗。

A组件的一个css样式影响了B组件的另一个同名样式。 组件组件的某个样式A意外的作用到了子孙组件的某个同名css上。

一般都会有一套自己的命名规则,比如在一个盒子布局里面有些同学固定就是.leftBox,.rightBox,.container。但是这样在一个很大体量的项目里使用一套命名规则,又会加重样式污染的概率。那也没办法,对于开发人员来说,给css命名是一件痛苦的事情。实在是憋不出那么多名字。

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

对于复杂或者庞大的项目来说,这些问题都已经见怪不怪了。过去接手过一个维护了很多年又比较大的远古项目,那里面的样式穿透,嘶~

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

为什么会有样式穿透的问题

这个得从咱们的项目对于css的引用规则说起。大家都知道,react组件的代码是不可以被浏览器识别的,我们编写react的代码可以在浏览器中被映射出来,是因为webpack把它编译成了一段浏览器可以识别的html。

我们简单的说webpack编译,这里就不展开,否则一个篇幅下来恐怕要没完没了了。

大概是这么个情况 再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

举个🌰,下图是一个react项目

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

他会被编译成如下这段浏览器可以识别的html代码。

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

接下来咱们说说为什么会有样式穿透。

假设组件A引入了一个css文件,该css文件里有一个类名为test,内容是color:red

组件B没有引入任何css文件,但是,组件B内存在一个一个名为test的类。

请问:组件B中这个名为test的类也会有color:red这个css效果吗

会有

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个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通常不鼓励深度嵌套,但通过自动生成唯一类名和使用预处理器**(如Sass、Less)可以提高开发效率和代码的可维护性‌。
css_modules是如何解决样式冲突的。

css_modules会在jsx被编译成html的过程中修改项目的css名称,让css加上一段唯一的随机字符串。让css和html的类通过这个唯一字符串形成唯一的映射关系。em....口述可能不能很好的表达,我们来个图看看。

下图:两个组件的类依然都叫test,这次不一样的是,通过css模块化修改了一下映射到浏览器上面之后的类名。 再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

这样就不会冲突了。

如何配置和使用css_module

每种框架对于配置css的具体细节并不一样,大家要配置的时候建议问chatGPT。

这里我们以vite框架来演示下less的配置和使用过程。

如何配置 css_modules

打开vite.config.ts 在css这个模块下按如下配置。

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

css: {

    modules: {

    // 你可以在这里添加自定义配置,例如全局的 CSS Modules 类名生成器

    generateScopedName: '[name]__[local]__[hash:base64:5]'

    }

}
如何使用css_modules
  1. 修改 [xxx].css 为 [xxx ].module.css
  2. 在需要映入css的文件内通过模块的形式引入,不要直接引入。例如 import "./index.css" => import styles from "index.css"
  3. 最后用映入的模块进行【styles.calssName】。例如 className={styles.test}

看不懂没事,有图⬇️。

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

PS:index.module.css文件内的css不需要做任何改变,该咋写咋写。

再也不用担心样式污染了!hello,同学们(早/中/晚)上好啊! 大家有样式污染,样式穿透的烦恼吗。 A组件的一个css

最后

PS: 在老项目里面追加css_modules功能是完全没有问题的,不会影响其他普通的css。

转载自:https://juejin.cn/post/7423066953039478822
评论
请登录