加载中...

CSS in JS (JSS)

JSS 是什么

简单来说,一句话概括CSS in JS (JSS),就是"行内样式"(inline style)和"行内脚本"(inline script)。

因为,自从React出现以后,基于组件化的要求,强制把HTML、CSS、JavaScript捆绑在一起,在同一个文件里面,封装了结构、样式、以及逻辑。这虽然违背html发明初期的"关注点分离"的原则,但更有利于组件之间的隔离。而每个组件包含了所有需要用到的代码,不必依赖外部环境,组件之间没有耦合。所以,随着 React 的走红和组件模式深入人心,“关注点分离”原则越发淡出人们的视野,而React所带来的"关注点混合"的原则逐渐成为主流。[1]

React 对 CSS 封装非常简单,就是沿用了 DOM 的 style 属性对象。CSS-in-JS是一种技术(technique),而不是一个具体的库实现(library)。简单来说CSS-in-JS就是将应用的CSS样式写在JavaScript文件里面,而不是独立为一些.css,.scss或者less之类的文件,这样你就可以在CSS中使用一些属于JS的诸如模块声明,变量定义,函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义。值得一提的是,虽然CSS-in-JS不是一种很新的技术,可是它在国内普及度好像并不是很高,它当初的出现是因为一些component-based的Web框架(例如React,Vue和Angular)的逐渐流行,使得开发者也想将组件的CSS样式也一块封装到组件中去以解决原生CSS写法的一系列问题。还有就是CSS-in-JS在React社区的热度是最高的,这是因为React本身不会管用户怎么去为组件定义样式的问题,而Vue和Angular都有属于框架自己的一套定义样式的方案。[2]

JSS 的常见实现

由于React 对 CSS 的封装非常弱,导致出现了一系列的第三方库,用来加强 React 的 CSS 操作。它们统称为 CSS in JS,意思就是使用 JS 语言写 CSS。根据不完全统计,各种 CSS in JS 的库至少有47种。老实说,现在也看不出来,哪一个库会变成主流。[1]

1. Styled-components

缺点:

  • 必须使用Styled-components预定义的语法糖,如styled.div("...")
  • 语法糖对css的封装居然使用的是string,而使用string也就意味着我们将会失去一切可能的对象化操作css的机会。这与差不多10年前 AngularJS 1.x 时代对 html 的处理方法如出一辙,不得不说这种方式似乎是在开历史的倒车。

不过,Styled-components 应该是CSS-in-JS最热门的一个库了,到目前为止github的star数已经超过了30k了。通过styled-components,你可以使用ES6的标签模板字符串语法(Tagged Templates)为需要styled的Component定义一系列CSS属性,当该组件的JS代码被解析执行的时候,styled-components会动态生成一个CSS选择器,并把对应的CSS样式通过style标签的形式插入到head标签里面。动态生成的CSS选择器会有一小段哈希值来保证全局唯一性来避免样式发生冲突。[2]

它既具备了 css-in-js 的模块化与参数化优点,又完全使用CSS的书写习惯,不会引起额外的学习成本[3]。

Styled-components官网

2. CSS module

import style from './index.css'
<div className={style.app}>

需要额外配置,ts环境需要配置*.d.ts的类型声明文件

declare module "*.css" {
    const css: {
        [key: string]: string //约定:导出key所在的对象,原始的类名和内容都会和转化为这个对象
    };
    export default css;
}

JSS 的好处

p.s. 接下来内容均转自 知乎/进击的大葱/CSS in JS的好与坏

1. 局部样式 - Scoping Styles

CSS有一个被大家诟病的问题就是没有本地作用域,所有声明的样式都是全局的(global styles)。而CSS-in-JS会提供自动局部CSS作用域的功能,你为组件定义的样式会被限制在这个组件,而不会对其他组件的样式产生影响。[2]

2. 避免无用的CSS样式堆积

进行过大型Web项目开发的同学应该都有经历过这个情景:在开发新的功能或者进行代码重构的时候,由于HTML代码和CSS样式之间没有显式的一一对应关系,我们很难辨认出项目中哪些CSS样式代码是有用的哪些是无用的,这就导致了我们不敢轻易删除代码中可能是无用的样式。这样随着时间的推移,项目中的CSS样式只会增加而不会减少(append-only stylesheets)。

而因为CSS-in-JS会把样式和组件绑定在一起,当这个组件要被删除掉的时候,直接把这些代码删除掉就好了,不用担心删掉的样式代码会对项目的其他组件样式产生影响。而且由于CSS是写在JavaScript里面的,我们还可以利用JS显式的变量定义,模块引用等语言特性来追踪样式的使用情况,这大大方便了我们对样式代码的更改或者重构。[2]

3 Critical CSS

放在head标签内的CSS当然是越少越好,因为太多的内容会加大html的体积,所以我们一般把用户需要在首屏看到的(above the fold)页面要用到的最少CSS提取为Critical CSS。

CSS-in-JS通过增加一点加载的JS体积就可以避免另外发一次请求来获取其它的CSS文件。而且一些CSS-in-JS的实现(例如styled-components)对Critical CSS是自动支持的。[2]

4. 基于状态的样式定义

CSS-in-JS可以根据组件的状态动态地生成样式。[2]

5. 封装得更好的组件库

如果CSS是写在JS里面的,项目想要使用封装的组件库只需要进行简单的npm install就可以了,非常方便。[2]

JSS 的坏处

p.s. 接下来内容均转自 知乎/进击的大葱/CSS in JS的好与坏

1. 陡峭的学习曲线

首先CSS-in-JS是针对component-based的框架的,这就意味着要学习CSS-in-JS你必须得学习:component-based框架(例如React),JavaScript和CSS这三样技能。其次,即使你已经会用React,JavaScript和CSS来构建SPA应用,你还要学习某个CSS-in-JS实现(例如styled-components),以及学习一种全新的基于组件定义样式的思考问题方式。[2]

2. 运行时消耗

由于大多数的CSS-in-JS的库都是在动态生成CSS的, 这就意味着会有一定的性能代价[2]

3. 代码可读性差

大多数CSS-in-JS实现会通过生成唯一的CSS选择器来达到CSS局部作用域的效果。这些自动生成的选择器会大大降低代码的可读性,给开发人员debug造成一定的影响。[2]

4. 没有统一的业界标准

CSS-in-JS只是一种技术思路而没有一个社区统一遵循的标准和规范,所以不同实现的语法和功能可能有很大的差异。[2]

总结

CSS-in-JS有好处也有坏处,要不要使用完全取决于同学们自己的项目需求。例如在下面几种情况下你就不需要它:

  1. 前端开发的初学者: 由于CSS-in-JS的学习坡度很陡,刚开始学习Web开发的同学没必要学习,可能会有挫败感。
  2. 功能简单的静态页面:逻辑交互不复杂的网站没有必要使用CSS-in-JS。
  3. 注重样式可读性以及调试体验: CSS-in-JS动态生成的选择器很影响代码的可读性,可能会降低你的调试效率。

在我们的课程中,我们CSS-in-JS和普通的css我们都会使用,所以请同学们放心,进过本课程的学习,同学们基本上能掌握如何使用不同的方式来定义React的样式了。

参考文献

posted @ 2023-03-27 17:07  辜负寒彻骨  阅读(1744)  评论(0编辑  收藏  举报
  1. 1 逝年 夏小虎
逝年 - 夏小虎
00:00 / 00:00
An audio error has occurred.

作词 : 刁云逸

作曲 : 夏小虎

风里飘雪的花

在记忆之中发芽

那些红色绿色

我们的青春年华

志向无限远大

转眼已各奔天涯

独自走在街上

只看见曾经的晚霞

时间似流水

催促我们长大

年轻的心有了白发

当初的人呐

你们如今在哪

是否也在寻找梦的家

风里飘雪的花

在记忆之中发芽

那些红色绿色

我们的青春年华

志向无限远大

转眼已各奔天涯

独自走在街上

只看见曾经的晚霞

时间似流水

催促我们长大

年轻的心有了白发

当初的人呐

你们如今在哪

是否也在寻找梦的家

时间似流水

催促我们长大

年轻的心有了白发

当初的人呐

你们如今在哪

是否也在寻找梦的家