传统开发模式

一般而言,在 Web 开发中,我们都会将 CSS、HTML、JavaScript 三者分离。

HTML 负责网页的结构。

CSS 负责网页上各个元素的展示样式(效果)。

JavaScript 负责网页与用户的交互(逻辑)。

将计算机程序划分为不同部分的设计原则,就是关注点分离原则(Separation of Concerns,简称 SoC)。因此,HTML、CSS、JavaScript 三者分离正是关注点分离原则的典型应用。

flowchart LR
	HTML(HTML  结构) <---> CSS(CSS 效果)
	HTML <--> JavaScript(JavaScript 行为)
	style HTML fill:#52c41a,color:white,stroke:#52c41a
	style CSS fill:#1890ff,color:white,stroke:#1890ff
	style JavaScript fill:#fa8c16,color:white,stroke:#fa8c16

什么是 CSS-in-JS

CSS-in-JS是一种样式技术,使用 JavaScript 编写 CSS,也就是把 CSS 集成到 JavaScript 中。这看起来有点反直觉。

解析这段 JavaScript 时,会生成 CSS(通常作为<style>元素)并附加到 DOM 中。

为什么会有 CSS-in-JS?

传统开发中,我们通常直接在 HTML 中引入 CSS 文件,样式缺少作用域隔离,很容易发生样式互相覆盖。

现代开发逐步走向组件化,也希望能让样式围绕组件边界生效。CSS-in-JS恰好可以做到“就近管理样式、减少污染”。

解决作用域问题

使用CSS-in-JS,就可以借助 JavaScript 作用域模拟 CSS 作用域,让 CSS 拥有独立的作用域,阻止 CSS 代码泄露到组件外部,防止样式冲突,使样式只在组件内部生效,从而解决 CSS 无作用域的问题。

增加组件的独立性、可移植性

移动组件时,我们可能会忘记样式文件,甚至不知道样式文件在哪里。使用CSS-in-JS,组件就是一个独立文件,只需移动组件本身即可,开箱即用,从而轻松创建松耦合的应用。

可重用性

只需编写一次,即可在任何地方运行,不仅可以在同一个应用程序中重用组件,还可以在使用相同框架构建的其他应用程序中重用组件。

动态性

CSS 缺乏动态性,不能根据条件给某个元素添加样式。使用CSS-in-JS,可以借助 JavaScript 的动态能力为元素动态添加样式,让复杂的逻辑也能应用于样式规则。特别是对于需要创建复杂动态 UI 的场景,它是理想的解决方案。

按需引入

随着业务量的增加,组件越来越庞大,因此需要按需引入。采用tree-shaking方式,使用CSS-in-JS更容易做到按需引入。

因此,CSS-in-JS方案就是为了解决 CSS 的局限性,例如缺乏动态功能、作用域和可移植性等问题。

优缺点

flowchart LR

  CSS-in-JS(CSS-in-JS) --> 优点(优点)
  CSS-in-JS(CSS-in-JS) ---> 缺点(缺点)

  优点 --> 作用域(作用域):::otherNode
  优点 --> 可移植性(可移植性):::otherNode
  优点 --> 可重用性(可重用性):::otherNode
  优点 --> 动态性(动态性):::otherNode
  优点 --> 按需引入(按需引入):::otherNode

  缺点 --> 复杂度(复杂度, 为项目增加了额外的复杂性):::otherNode
  缺点 --> 降低了可读性(降低了可读性, 自动生成的选择器大大降低了代码的可读性):::otherNode

	style CSS-in-JS fill:#F8840D,color:white,stroke:#F8840D
	style 优点 fill:#52c41a,color:white,stroke:#52c41a
	style 缺点 fill:#f5222d,color:white,stroke:#f5222d
	classDef otherNode fill:#1890ff,color:white,stroke:#1890ff

总结

它特别适合在组件库中使用。

CSS-in-JS只是一种模式,需要框架的支持。

常用的框架有: