用 styled-components 在 react 中编写 css

这么久以来,各种各样的框架试图让 web 组件化。到目前为止,react 基本做到了这一点:用一个自定义标签的方式组织 html 在一起。

<Wrapper>
    <Header />
    <ProductList />
    <Footer />
</Wrapper>

上面的这种写法在传统的 web 开发中真是不敢想象,然而在 react 中的确实现了。如果你使用 create-react-app 这样的脚手架工具,你可以快速的搭建起来这样的体系。然而,即便是这样子,web 组件化依然有一个点没有解决:如何将样式和组件绑定在一起。当然,试图解决这个问题的工具有很多,也有很多人不认为这是一个问题。我在这里试图解释一些观点,并阐述为什么我觉得用 styled-components 可以在一定程度上解决一系列问题。

写 css 的最佳方式

目前,react 阵营对写 css 这个问题有两个阵营。一个阵营表示 css 应当和 js 写在一起,而另一个阵营则认为 css 原本是可以和 js 分离的。我们在这里做一个简单的例子。

首先是 css in js 的例子:

const style = {
    margin: "1em 2em",
    color: "gray",
    background-color: "white"
};

const StyledDiv = (props) => {
    return <div style={style}>A test</div>
};

而 css 和 js 分离就很简单了:


.styled-div {
    margin: 1em 2em;
    color: gray;
    background-color: white;    
}

import "./StyledDiv.css";

const StyledDiv = (props) => {
    return <div className="styled-div">A test</div>
};

当然,这里展示的 css in js 只是一种非常原始的方式:用 object 直接将 style 注入到组件中。这样做的好处有两个:

  1. css 不在是全局的了,style 的生命周期与生命范围终于和 component 一致了,那么因为全局变量导致的可怕的为何灾难缓解了
  2. 在组件内对样式的操纵可以直接进行,无需通过 className 处理,当然也避免了创建全局的 className 了

可以看到,这里基本上就是以解决 css 的全局性为出发点的。

而 css 和 js 的分离当然也有其天然的优势:

  1. 可以用 css 的方式写 css,css 选择器随便用
  2. 我还可以加各种 preprocessor 和 post processor,比如写 scss 比如加 auto-prefix

对我来说,用 object 的方式去写 css 体验实在是太差了。而且作为 csscascade,如果不能用多级的选择器去定位 css 而是在一层层的 html 元素中添加样式简直就是噩梦。我不觉得这样的可维护水平比全局 css 要高...所以我觉得如果能把两者的优势结合在一起,就应该是一个可以被更多人介绍的方式:

  1. 用 css 的语法写 css
  2. 能创建局部 className
  3. 支持 preprocessor 和 postprocessor

那么在这里就不得不提另外一个有意思的东西:css-modules。它的主要思想是通过为 css 生成随机的类名称的方式来建立一种局部类命名的方式。

styled-components 基本上集成了这个工作,并在此基础上基本实现了以上的三点要求。

const Summary = styled.div`
  margin-top: 2em;
  text-align: right;

  .price {
    color: #ff0036;
    font-size: 1.2em;
  }

  &> * {
    display: inline-block;
    margin-left: 1em;
  }
`;
  1. Summary 的 css 是以 css 的方式编写的,支持多层次的定义
  2. styled-components 会把上面定义的 css 以一个特别的 className 的方式注入到元素上,实现了局部类定义
  3. styled-components 支持了基本的类似于 scss 的嵌套语法(还支持 extend 语法,这里并没有展示),并且内嵌了 autoprefix 的模块

我最近开始在一个项目上使用它,整体来说还是感觉不错。

兼容现在已有的 react components 和 css 框架

styled-components 采用的 css-module 的模式有另外一个好处就是可以很好的与其他的主题库进行兼容。因为大部分的 css 框架或者 css 主题都是以 className 的方式进行样式处理的,额外的 className 和主题的 className 并不会有太大的冲突。你可以认为这是一个应当使用全局 css 的地方(所以我并不赞成用 styled-components 里面的 theming 接口去做这件事)。相对于以 object 的方式写 style 的 material-ui 真是好太多了,看看 material-ui 讲述如何进行样式自定义就知道这并不是一个很成熟的想:

  1. css 内嵌到组建里影响了组件自身结构的表现
  2. inline style 意味着最高的优先级,其无法和其他的主题库配合

styled-components 的语法同样支持对一个 React 组件进行扩展:

const StyledDiv = styled(Row)`
  position: relative;
  height: 100%;
  .image img {
    width: 100%;
  }
  .content {
    min-height: 30em;
    overflow: auto;
  }
  .content h2 {
    font-size: 1.8em;
    color: black;
    margin-bottom: 1em;
  }
`;

这里我把 ant design 做为我默认的样式库,在其基础上我对其一些元素做了增强。两者可以很好的在一起使用。

这里符一个 github 项目 里面包含了很多使用 styled-components 的例子。

相关资料

  1. scss
  2. js in css
  3. styled components
  4. auto-prefix
  5. material-ui
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,544评论 25 707
  • 原文地址:react-css-modules阅读本文前建议了解 CSS Modules 的知识。墙裂推荐阅读 Ca...
    梁相辉阅读 2,189评论 1 18
  • 是一句还是一万句? By/夭夭 没有神的世界里,人只能一辈子都在寻找,寻找一个人,和他说一句知心的话,一个人内心的...
    李珩玉阅读 240评论 0 0
  • 周末上完舞蹈课,几个小小朋友聚集在体育馆的广场玩,朵朵上一年级了,学会了轮滑,四个小姑娘轮流穿着她的轮滑鞋,每个小...
    喜欢小草阅读 187评论 0 0
  • 今天早上我们去吃自助餐。果蔬好的卡在我的包里,所以是我刷的卡,刷完卡是需要签字的,但是签字的时候我根本没有看单子上...
    张续飞阅读 158评论 0 0