所谓成熟就是,你要习惯任何人的忽冷忽热,也要看淡任何人的渐行渐远。
前言
在react中css没有作用域
scoped
的概念,虽然是为每个组件创建单一的.scss文件并在入口引入,但依然是全局的。scss的嵌套理想状态和css的选择器层叠一样不错过3层,处理器也很难保证为每个组件都编译出单独的css文件。
使用
不管是在哪种环境之下使用,CSS Modules的使用都不会有太大差异,只会稍微的细节上的差异。
样式默认局部
使用了 CSS Modules 后,就相当于给每个 class 名外加加了一个 :local
,使用:global转换。
1 | .normal { |
Composes 组合样式
CSS Modules 只提供了唯一的方式
composes
来复用样式
1 | /* components/Button.css */ |
1 | import styles from './Button.css'; |
由于在 .normal
中 composes 了 .base
,编译后会 normal 会变成两个 class
composes 还可以组合外部文件中的样式
1 | /* settings.css */ |
对于大多数项目,有了 composes
后已经不再需要 Sass/Less/PostCSS。但如果你想用的话,由于 composes
不是标准的 CSS 语法,编译时会报错。就只能使用预处理器自己的语法来做样式复用了。
class 命名技巧
CSS Modules 命名规范 BEM 扩展
- Block:对应模块名,如 Dialog
- Element:对应模块中的节点名 Confirm Button
- Modifier:对应节点相关的状态,如 disabled、highlight
BEM 最终得到的 class 名为 dialog__confirm-button--highlight
。使用双符号 __
和 --
是为了和区块内单词间的分隔符区分开来。
CSS Modules 中 CSS 文件名恰好对应 Block 名,只需要再考虑 Element 和 Modifier。
1 | /* .dialog.css */ |
另外,CSS Modules
采用驼峰命名只是建议,而不是强制,因为{style.class-name}
不支持,但是你依然可以通过 {style['class-name']}
使用。
实现CSS,JS变量共享
:export
关键字可以把 CSS 中的 变量输出到 JS 中。
下面演示如何在 JS 中读取 Sass 变量:
1 | /* config.scss */ |
使用技巧
使用CSS Modules 一般要遵循一些规则
- 不使用选择器,只使用 class 名来定义样式
- 不层叠多个 class,只使用一个 class 把所有样式定义好
- 所有样式通过
composes
组合来实现复用 - 不嵌套
react实践
1 |
|
注意,一般把组件最外层节点对应的 class 名称为 root
。
另外 ,如果你不想频繁的输入 styles.**
,可以试一下 react-css-modules,它通过高阶函数的形式来避免重复输入 styles.**
。
CSS Modules 结合历史遗留项目实践
外部如何覆盖局部样式
当生成混淆的 class 名后,可以解决命名冲突,但因为无法预知最终 class 名,不能通过一般选择器覆盖。我们现在项目中的实践是可以给组件关键节点加上 data-role
属性,然后通过属性选择器来覆盖样式。
如
1 | // dialog.js |
因为 CSS Modules 只会转变类选择器,所以这里的属性选择器不需要添加 :global
。
如何与全局样式共存
前端项目不可避免会引入 normalize.css 或其它一类全局 css 文件。使用 Webpack 可以让全局样式和 CSS Modules 的局部样式和谐共存。
1 | //webpack部分配置 |
这样所有全局的样式都放到 src/styles/app.scss
中引入就可以了。其它所有目录包括 src/views
中的样式都是局部的。
原文链接:https://blog.csdn.net/xiangzhihong8/article/details/53195926