从关注点分离到css-in-js

By
写代码

一直以来,前端推崇“关注点分离”的原则:即HTMLCSSJavaScript被拆分在不同的(一个或者若干个)文件里。写页面时,需要按照需要,引入不同的css和js文件。这样做的好处显而易见:页面结构清晰,没有css样式的杂糅,方便抽取公共组件。由于大部分任务都是页面级别的,粗粒度开发,这一点是很有必要的。再加上网络带宽限制,在很长一段时间里,前端程序员以抽取更多的公共样式为追求目标。并且不断被告知,不要写内联样式,很low而且无法维护。

css有没有什么不足呢?当然有,比如说:

  1. 1、全局变量。定义了一个样式名,就相当于写了一个全局变量,作为前端程序员,还不知道全局变量的缺点吗?你唯一能做的就是祈求不要和别人的重名或者优先级不够(过高)造成样式覆盖,否则,你需要写btnbtn-defaultbtn-default-adjust这样越来越长的名字来调整;
  2. 2、重复引用。重复引用很常见:比如大组件的引用了一个layout.css,其中包含了button的样式定义。嵌套的小组件,也需要用button的定义,但是somehow这个人不知道,就很容易造成重复引用,虽然冗余,但是还生效;
  3. 3、无用代码。随着项目迭代,许多新样式加入,旧的代码被废弃。但是缺乏检查机制,或者选择器相互关联,造成代码无法维护;
  4. 4、共用变量。比如需要定义全局的背景颜色、block阴影类型、按钮颜色等。

出现组件拆分之后的style

随着前端结构的发展,页面被拆分成了越来越细粒度的组件,起初我们会把一个界面拆分成header、body、footer三个组件,然后依据页面需求拆分出诸如multiselecttab等公共组件。之后受各大UI库的影响,我们开始进一步拆分:负责数据请求的组件,负责动画的组件,tablebannerlightbox。然后是更细粒度的:table中负责header的,header各个item的,item中不同风格的等等。

并且,由于React/Vue这类库更提倡将组件信息写入单个文件,即融合HTML标签、style样式、JavaScript的单文件组件。如下面这样

猛一看,这不是内联样式吗?不是说不要随便用内联样式吗?仔细看看,style传入的,其实是个Object,负责组件的样式定义。

但是直接这么写,用户肯定不接受啊,所以社区贴心为我们准备了css-loader(或者scss-loader等)大礼包,通常包含在各个使用webpack的脚手架(cli)里。这类插件,统称为css-in-js

所以,我们可以像以前一样,把css写在不同文件里,甚至继续使用scss,并且嵌套等css的优势好像又回来啦,当然也包括缺点。

你可能没注意,React官方文档里,只写了一个className的作用,而看不到关于样式文件的定义。随之抛给你一些css-in-js的插件,并表示:我们对于如何定义样式不持有任何立场。你琢磨琢磨,这几个意思。

css-in-js的缺点

  1. 1、更多的嵌套层级。由于多了样式组件(styled component),即专门控制样式的组件容器,所以生成的代码复杂程度更高。这一点对于较小规模的App尤其明显;
  2. 2、代码易读性差。代码洁癖直接劝退。以前只需要找对应的css文件即可,起码语法是没问题的。当混合了函数,情况就不一样了。需要在组件中寻找不同的定义、扩展以及相互的覆盖关系等内容。比如下面的

顶部的/** @jsx jsx */表示用emotion的jsx替换默认的jsx。jsx是React中用以把html结构的内容

转换成

这样可执行代码的函数。这个转换器支持替换为自定义(通过json配置或者注释)。

css-in-js优点

  1. 1、本地scope控制(local scope)。有点类似Vue,生成的class是有动态id的,组件间不至于相互影响,又能使用父级和全局样式;
  2. 2、支持函数。由于本质是JS代码,所以处理复杂逻辑是完全没问题的,可以任意使用循环、变量、基于状态变化的样式等;
  3. 3、方便抽取公共组件。由于样式完全跟随组件,所以可以方便的把样式相关的逻辑迁移到任意地方。

所以,emotionrebass这些库到底香不香,哪个更香?

这里有一篇对比

css in js compare

0

Comments: 1

  1. 不管这里经历了什么,我会常来看看。(继续监督中。。) :cry:

    2019年12月26日

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

:razz: