最后, 便是...[原文里没有,翻墙没成功,所以我也不知道是什么]。它提供了一种方法来隔离CSS和JS文件的运行时间,但与此同时,也会增加启动成本--来源于延迟和维护成本--来源于内存的保持。然而通常情况下,这种折中是值得的。 对于大多常用网站的嵌入(如:Facebook, Twitter, Disqus等)都是使用 iframes实现的. 然而对于本文想实现的目标--将成千上万的小组件相互分离--而言,这种方法会大幅度降低我们的预期。
不管怎么样,这节的篇幅有点长了,让我们回到我们所列的CSS规则上吧。
7. 考虑组件的边界问题
正如 .myapp-Header > a
这条规则一样,当我们想嵌入子元素的时候 ,我们可能需要对子元素应用相应的样式规则 。而不像web组件一样,在处理> a
和 > my-custom-a
时没有任何区别。考虑下面这个布局:
+---------------------------------+| Header +------------+ || | LoginForm | || | | || | +--------+ | || +--------+ | | Button | | || | Button | | +--------+ | || +--------+ +------------+ |+---------------------------------+
我们能马上注意到设置.myapp-Header .myapp-Button
这样一条规则会非常糟糕,所以我们会使用.myapp-Header > .myapp-Button
这条规则。但是什么样的规则才是我们想应用到子元素中的呢? 当想让 LoginForm
元素位于Header
元素的右侧时,有人会这样定义:
.myapp-LoginForm { float: right;}
这个定义没有违反我们制定的任何规则,但是这会使得LoginForm
的样式规则不太好被重用。例如:当页面想重复使用LoginForm
元素时, 此时重用的的LoginForm
就并不具备向右浮动的布局。哎,真糟糕!此时,通常的解决方法就是放宽先前指定的规则,而使得该规则可以应用到该文件所属的命名空间中。也就是说,我们应该如此制定规则:
.myapp-Header { > .myapp-LoginForm { float: right; }}
只要你不随意地设置会影响到子元素盒模型的样式,这个规则还是能很好地起作用的。
// 不好的例子; 不要这样做.myapp-Header { > .myapp-LoginForm { color: blue; padding: 20px; }}
我们不允许这样做的原因是在于这样的设置会打破局部修改不应该对全局造成影响的原则。并且使用了上述编码之后,LoginForm.scss
文件就不再是你在需要改变LoginForm
组件元素样式时所需要考察的唯一文件了。这时的改变将牵连甚广。那么可不可以的评判标准是什么呢?
为了不依赖于样式的实现细节,我们希望每一个子组件都能有其自己的“界限”。也就是说,对于我们而言,它们是黑盒。相反地,这些子组件之外的便隶属于父组件自身。内、外的区分来自于CSS中的一个最基础的概念: 盒模型.
我的类比很糟糕,但接下来的不是:就像“在一个国家”意味着在其物理边界中一样,我们声明在border外部有一个父元素可以对其内的(直接)子元素的样式造成影响。也就是说,那些会影响定位和尺寸大小的属性,如:position
, margin
, display
, width
, float
, z-index
等在外部(父元素)中声明是被允许的,但是那些会对边界里的内容造成影响的属性,如:border
, padding
, color
, font
等的设置就是不被允许的。 是以,按照该推论,下面这样的方式也是不被允许的 :
// 反例; 不要这样做.myapp-Header { > .myapp-LoginForm { > a { // relying>8. 松散的聚合外来样式为了避免重复的工作,有时也需要使得不同的元素间共享样式规则。而为了逃避这一工作,你可能会想使用由其他人创建的样式。但无论是哪一种方法,都应该保证不会在代码库中创建不必要且耦合的代码。 作为一个具体的例子,让我们考虑使用Bootstrap--作为一个规避了这些问题的框架--中的一些样式。Bootstrap考虑到了上面所讨论过的问题,也使用了单一的全局命名空间来管理样式,但有以下不好的点: