背景
样式是组件库必不可少的一环。但是关于一个组件库 CSS ,涉及到方方面面,例如:模块的划分、状态的划分、元素的划分等。但是如果没有一个好的规则,即使我们使用 Scss、Less 这样的便利工具,我们也无法保证每个参与共同开发组件库的同学的 CSS 结构统一。
我们应该遵循一种标准来构建我们的组件库文件结构,使每个组件最终转换为 CSS 后更加清晰,模块、状态、元素的分工也更加明确。这就是 BEM 规范。
BEM 规范
定义
BEM 是一种书写 CSS 的规范,是由 Yandex 团队提出的一种前端 CSS 命名方法论。其目的是为了明确 CSS 作用域,确定相关 CSS 优先级,分离状态选择器和结构选择器。
再说白点就是为了约束你写 CSS 的习惯,使你书写的CSS更加语义化。
B - block:表示一个块元素,比如一个 Modal 弹窗组件、一个 Button 组件,都可以用一个块来表示。 E - element:表示一个子元素,存在于块元素之内,例如弹窗组件的 title、footer。 M - modifier: 表示修饰符或者状态,例如 Button 组件的选中态、销毁态。
Block - B 的块元素会直接表示:.block。 Element - E 的子元素类型会由双下划”“线表示,并且嵌套进 block 元素后:.blockelement。 Modifier - M 的修饰符则会由中划线表示”-“, 并嵌套在 块元素,或者子元素之后:.block-modifier 或.block__element-modifier。
BEM 规范的优势
- 组件之间都遵循 BEM 结构规范,会使代码维护成本大大降低。
- 使我们的组件库的代码更加规范清晰。可维护、可读性高。
Less、Sass 如何选择?
随着前端工程化的发展,出现了各种预编译的规范像 Less、sass 等等。它们依靠工程化的基础,引进了嵌套、变量、混入、选择器、继承等等特性。使相同的逻辑可以抽离,维护起来也更加舒服。
并且经过编译后,也能较为准确地还原 CSS 文件,达到一致的效果。所以,越来越多的项目开始使用预编译 CSS,现在看来,它已经无处不在,各大组件库100%都使用了它们。在所有 CSS 预编译语言中,SASS/SCSS 依旧是使用范围最广、最成熟的。但是个人觉得 Less 亦或者是 Sass 都可以作为组件库的 CSS 预编译工具。在 Element 组件库使用 Sass 作为预编译工具,在 Antd 组件库中则使用 Less 作为编译工具。所以 CSS 编译工具的选择似乎不是很重要。
如何组织样式文件?
我们可以看看 Element 组件库和 Antd 组件库是如何组织样式文件的,毕竟他们都已经很成熟。『站在巨人的肩膀上,会让我们看的更远。』
Element 组件库
Element 组件库的样式是放在 「theme-chalk」的文件夹存放,并且直接放在 packages 目录下。整个组件库的样式文件全部收拢在此文件夹下。在组件中是看不到有样式文件定义或者 style 的书写。
所以就 Element 组件库而言是把所有的样式文件集中管理,在进行样式文件逻辑的复用、拆分和依赖。
这样设计的优点就是:
- 样式比较集中、架构比较清晰;
- 方便扩展,生成不同的主题包进行引入;
- 可以由脚本统一处理兼容性、压缩等。
但是缺点也很明显:
- 开发过程中需要反复横跳两个 package 进行调式,比较繁琐。
Antd React 组件库
在 Antd 的组件库中会抽离一个公共的 style,并且在具体的组件中也会定义 style。这和 Element 是背道而驰的一种方式,是分散到各个组件文件夹内部的,再通过脚本进行编译整合压缩。
这样的好处就是:
- 比较直观地进行代码样式的修改,不需要像 element 那样反复横跳。
但是缺点也比较明显:
- 组件相互结合的方式,使得我们修改样式和逻辑相互耦合,维护成本比较高。
总结
上面我们看了两种比较主流的组织样式文件架构的方式。各有利弊。如果你要开发一个组件库,到底是选择 Element 的集中管理,还是 Antd 的分散处理,需要具体方案具体分析。作者本身也不能善判到底选择那种方式。