简介
CSS-in-JS是什么,看到这个词就能大概猜到是在JavaScript里写CSS,那为什么要在JavaScript里写CSS呢,像之前一样写在css文件里哪里不好么?
(图片来自:http://t.cn/R6njCiV)
在介绍这个概念之前,先来回顾一下在日常编写CSS代码时都有哪些痛点:
进化史介绍
在CSS的进化历史上,出现过各种各样的框架致力于解决以上的问题:
可以看一个简单的CSS Modules例子了解一下:
生成的dom结构如下图,基于css文件中的class名称生成了唯一的class名称,样式会定义到生成的class上。
styles打印出来如下图,定义了css中的class名字和生成的唯一class名字的对应关系。
可以看出,以上框架都解决了不少痛点,但也还是各有一些不足,当然CSS-in-JS也并不是完美的解决了所有问题,我们先来详细介绍一下。
流行框架介绍
现在随着组件化概念的流行,对从组件层面维护CSS样式的需求日益增大,CSS-in-JS就是在组件内部使用JavaScript对CSS进行了抽象,可以对其声明和加以维护。这样不仅降低了编写CSS样式带来的风险,也让开发变得更加轻松。它和CSS Modules的区别是不再需要CSS样式文件。
来看一下几个流行的CSS-in-JS框架六个月内的下载趋势:
我们来看看几个下载量靠前的框架的风格是什么样的:
styled-components
先来看看下载量最高的styled-component的代码风格:
从上图可以看出,Title和Wrapper都是框架包装好的component,可以直接在react的jsx语法中使用,在包装component的时候还定义了标签分别是h1和section。此段代码产生的html dom如下图所示:
可以看到section和h1上分别生成了唯一的class名称,样式也对应的定义在生成的class上了。 这样就可以解决命名混乱和全局污染的问题。组件相关的代码都在一起,可以统一查看,也可以方便的重用样式。
glamorous
再来看看glamorous,这个框架是PayPal开发的。(前两个logo看下来,恍惚间感觉进了化妆品专柜)。
和styled-component不同的是,glamorous的样式直接以attribute的形式定义在了dom上,之后虽然也为其生成了class名称及样式,但这种以attribute定义的方式对伪类选择符(如 :hover)支持的不好,会带来一些不方便,而且需要再记住一套attributes名称和值与真正的css样式代码的对应关系。
JSS
和上面两个框架类似,jss也是会定义styles对象,并附到component上,最后生成的dom也是会有生成的唯一class名称,并有对应的样式,但样式并不是真正的css语法,而是对象的属性和值,这样也是对伪类选择符支持的不好,而且也需要记住属性和css样式代码之间的对应关系。
Radium
Radium在定义样式对象上看似和其他相似,但在生成dom结构的时候并没有生成唯一的class名称,而是直接把样式放到了style属性上,这样会带来诸如可读性差、CSS权重过大、不支持伪类选择符等问题。
测试
下面再来看一个styled-component提供的基于jest的测试框架:
jest-styled-components
这个框架主要是通过生成Snapshot并比较的方式来保证component样式的每次更改都会被检测到,并且样式是期望的样式。这样就又降低了重构CSS样式带来的风险。
优劣势总结
看了这些框架后,可以发现CSS-in-JS的优势还是挺多的:
但是CSS-in-JS也存在着一些不足和争议:
最后
在ThoughtWorks最近一期的技术雷达(CSS-in-JS | Technology Radar | ThoughtWorks)里,它的等级是Assess,表示的是:“值得追求。重要的是理解如何建立这种能力。企业应该在风险可控的项目中尝试此技术。” 所以最后想说的是,虽然它还是有些不足和争议,在应用之前需要多角度衡量一下对项目的适合度。但它的优点也很多,确确实实解决了很多痛点,而且与web组件化的方向高度一致,希望大家在条件合适的情况下多多尝试,多多反馈,这样也能促进整个CSS编码体验的继续进化~