这些原则都是我从这些年工作中所含盖的各个大型、复杂的web项目中总结出来的。而这些事情也都是我这些年被多次问到的,所以觉得将其用文档的形式叙述出来会是个不错的想法。
我会尝试着尽量缩短我的解释,以下是关键词:
善用类来定义CSS
将组件的相关代码放在一起
使用一致的类命名空间
让命名空间和文件名间具有映射关系
防止在组件外定义样式
### 防止泄漏组件内的样式
考虑元素的边界问题
松散的聚合外来样式
简介
如果你从事前端的应用开发,那么你一定会需要设置样式。尽管现在优秀的前端应用花样百出,但CSS仍然是赋予网页上任何东西样式的唯一方法(但是,在某些情况下,原生的应用也可以做到)。也就是说,这篇文章将讲到两大类设置样式的方法,即:
已存在多年的 CSS 预处理器,如:SASS, LESS等)
相对而言,才出现的具有CSS-in-JS 特性的库 (如 free-style, 和 many others)
对于这两种方案的选择完全可以另立文章进行讲解。当然, 它们也都有各自的优缺点。尽管如此,我将集中介绍前一种方法, 所以,如果你选择“追随”后者,那么这篇文章对于你而言会比较乏味。
高层次目标
我们追求的是一个稳固的、可升缩的CSS框架。但是要做到这一点,究竟需要具备些什么特质呢?
面向组件 - 处理UI复杂性的最佳方法就是讲UI分成许多很小的组件。如果你使用了一个“明智的”框架,你就会发现在JS方面也是如此。 比如,React就具有高度组件化的特性。由此,我们希望CSS框架也能如此。
沙盒 - 将组建进行拆分并不一定能能使得其按照我们的期望进行加载,如:一个组件的样式可能会对其他组件的样式产生不可预计的影响。诸如cascade这样的CSS基础特性和具有唯一全局性性质的命名空间的标识符就能造成这种影响。如果你对 Web组件的规范比较熟悉, 你就可以开始考虑利用 Shadow DOM可以隔离样式的优势 来做些什么而不必去关心浏览器的支持程度(或是否有相应的规范)。
易用性 - 我们想要一切“漂亮”的事物,但是又不想做过多工作。也就是说,我们并不想要开发者在运用该框架时具有较差的体验。如果可以,我们想将其做的更好。
容错性 - 与前面的观点有点联系的是,我们希望一切的东西默认都具有本地性,当然,异常除外。而我们工程师都很懒,而通常阻力最小的方案总被证明是正确的解决方案。
一致性原则Concrete rules
1. 善用类来定义CSS
This is just to get the obvious out of the way.
不使用ID (e.g. #header
), 因为当你认为这将只是一个事物的实例的时候,你都会被现实-- 在无限的时间尺度上]--很扇一个耳光。这是我们过去发生过的一个案例。当时我们尝试着去剔除一个大型应用中的数据绑定bug,因此我们在同一DOM树中并列使用了两个运用了这个UI库的实例, 而这两个都绑定到了一个名为shared的实例上。 最初,这是为了保证数据模型中的所有修改都能正确的反映到UI库上。然而此时,任意你觉得会是独一无二的组件,如:header bar,都将不复存在。这也是一个发现与独特性假设相关的不易察觉的bug的标准方法。 这个事情的道理在于: 没有相关的解决方法会使得运用ID的方法比运用class的方法好。 所以让我们永远不要使用ID吧。
同样的,你也不能直接指定你的目标元素。 但是如果目标元素在某个组件里,直接指定到是可行。但最终,你需要去清除这些对于组件而言无用的样式 。 而对于我们更高级别的目标来说,这与其是完全相背离的。而设置body上的属性,如:fonts、 line-heights 和colors (又名可继承的属性) 却是一个特例。 但是如果你格外在意组件的独立性的话, 放弃这些是完全可行的(如 使用外在样式中所说的一样).
所以,除了某些特定的场合,你的样式设置最好使用class。
2.将组件的相关代码放在一起
当在设置一个组建的时候,如果能将其相关部分--js文件、css文件、测试文件等--聚集起来,会对组件的组件化起到很大的作用。