styled-components—论React如何优雅地写CSS
前言
好好的HTML、JavaScript、CSS为什么要写在一起,分开来写不是更好吗,这样也避免一大串合在一起影响美观呀,但是自从学习了React框架后,发现HTML和JavaScript写在一起,但是CSS写在另外一个文件,刚刚接触React时才疏学浅,认为这应该是祖祖辈辈传下来的吧,但是经过一段时间,发现这并不好维护,每个js组件带一个CSS文件,不仅在HTML中要设置class属性,还必须要用在每个css样式里面带上组件的前缀生怕污染全局css,内心不爽却也无能为力。
直到我遇见了,styled-components,仿佛像是沙漠旅行者遇见了绿洲~
为什么要CSS in JS
这点就好比一个袋子标签写着‘钥匙’里面装了所有与钥匙相关的东西,而不是一个大袋子装钥匙,还附带一个小袋子装钥匙扣钥匙环。这样相比就很明白了,我们可以理解CSS为钥匙扣和钥匙环,在传统的样式脚本分离的写法中,需要手动将钥匙和钥匙环扣在一起才能使用。但是CSS in JS就好比将钥匙环已经绑定在钥匙上,拿起即用一样。
安装
1 | npm install styled-components |
styled-components只需要安装一次,便可以像一个组件一样在任何地方使用,并不需要配置webpack,这一点充分体现出开箱即用的优点,我们先从一个简单的demo来展示他最基础的用法。
1 | import React from "react"; |
相信你看完这段代码后,会有种 真 · 组件式开发 的感觉,直接将css写在自己定义的一个组件中,在render里面直接调用,不必写一些className乱七八糟的属性。但是,这只是styled-components的最大的特点,关键是,写CSS最重要的还是完全复原设计图,styled-components得要又其他css类库一样简便的用法。
组件样式继承
通常在原生css中一般会通过在class中传入多个name通过空格分隔来复用css样式,这样也起到了继承的作用,但是在styled-components中继承是一件非常优雅的事情,就像写class继承那么优雅:
1 | class App extends React.Component { |
在这里,我们用到了类似于ES6中class的extend的语法,无论是在书写美观还是可读性,styled-components都略胜一筹,你的小伙伴也无需看到你class里面装满css的name而头皮发麻啦~
随意更换标签
我们经常会遇到这样的情况,当我们写完一个button的样式后,在一些奇怪的场景下,我们必须要使用a标签来替换button标签,并且a标签和button所要求实现的样式是一样的,这个时候你可能会复制一份button的样式再加到这个a标签中,但是在styled-components中,你可以随意切换标签,代码如下:
1 | class App extends React.Component { |
继承样式后,通过withComponent来切换标签,随意自如,是那么的优雅~
用props定制主题
我们使用antd的时候,同一个Button通过设置来使用各种样式的按钮,千万不要觉得这很难实现,因为在你自己项目中,自己也能够很方便地是用styled-components的props传参来定制,代码如下:
1 | class App extends React.Component { |
设置attrs函数
只是优雅当然不够,还得有html和css的最原始的功能,比如说input里面设置type来定义不同类型的输入框,不知你是否忍受够了在input标签里面书写长长一大串属性(type value class)带来的密集感,要知道如果标签中写的属性过多,会极大地降低html结构的可读性,但是,有了styled-components,一切都可以变得那么优雅~
1 | class App extends React.Component { |
嵌套和伪类
之所以对styled-components很亲切,是因为他的语法和less有很大的相似之处,并且在styled-components,我们依旧可以使用className来定义样式,如下代码:
1 | class App extends React.Component { |
CSS 动画支持
同样动画也是完美支持,和元素CSS写法并没有太大区别,注意要引入styled-components的特定keyframes,代码:
1 | import styled, { injectGlobal, keyframes } from "styled-components"; |
为什么不污染全局样式
最后我们留下一个问题,我们之前在使用css-modules中,之所以它不会污染全局css样式,是因为构建工具会将类名style.title编译成一个哈希字符串,保证每个class不重复,那么styled-components的原理是怎么样的呢?
我们打开chrome调试工具可以发现:styled-components同样也为class生成了唯一的哈希,并且无需在webpack共建工具中配置任何项目,开箱即用~

总结
styled-components在实际开发过程中,我认为最主要还是优化了HTML结构的”美感”,使得代码可读性更好,也提升了组件可维护性和代码复用率,并且引进了很多先进的概念,使得写CSS能够像写JavaScript一样灵活,这对于我们用JavaScript写html的React脑残粉来说,是个“三国统一”的最终愿景,当然这只是styled-components的部分功能,还有更多的功能等待我们去发现,小生学疏才浅,只是抛砖引玉,顺便写一篇博文巩固自己对知识是掌握。