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]。
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有好处也有坏处,要不要使用完全取决于同学们自己的项目需求。例如在下面几种情况下你就不需要它:
- 前端开发的初学者: 由于CSS-in-JS的学习坡度很陡,刚开始学习Web开发的同学没必要学习,可能会有挫败感。
- 功能简单的静态页面:逻辑交互不复杂的网站没有必要使用CSS-in-JS。
- 注重样式可读性以及调试体验: CSS-in-JS动态生成的选择器很影响代码的可读性,可能会降低你的调试效率。
在我们的课程中,我们CSS-in-JS和普通的css我们都会使用,所以请同学们放心,进过本课程的学习,同学们基本上能掌握如何使用不同的方式来定义React的样式了。
参考文献
- [1] 阮一峰的网络日志/CSS in JS 简介
- [2] 知乎/进击的大葱/CSS in JS的好与坏
- [3] Styled Components: Enforcing Best Practices In Component-Based Systems
- [3] JSS
- [4] wikipedia
CSS in JS (JSS)的更多相关文章
- 了解CSS in JS(JSS)以及在React项目中配置并使用JSS
目录 认识JSS 什么是JSS JSS 的常见实现 JSS 的好处与坏处 好处 坏处 使用模块化CSS实现JSS 安装插件 在React项目中的tsconfig.json中添加配置 vscode项目中 ...
- JQuery 加载 CSS、JS 文件
JS 方式加载 CSS.JS 文件: //加载 css 文件 function includeCss(filename) { var head = document.getElementsByTagN ...
- grunt自定义任务——合并压缩css和js
npm文档:www.npmjs.com grunt基础教程:http://www.gruntjs.net/docs/getting-started/ http://www.w3cplus.com/to ...
- 来,一起让我们越来越懒,面向CSS、JS未来编程。(9.28已更新)
2016.10.29更新 本文存在大量的错误,仅供参考. 不知不觉在前端领域马上一个年头就要过去了,然而再看看自己的代码,果然够烂,那么为什么代码一直没有用面向对象的思维去写CSS呢?首先有两点:一点 ...
- 如何判断一个DOM元素正在动画,一个CSS“阻塞”JS的例子
一般情况下CSS不会直接影响JS的程序逻辑,但是以CSS实现动画的话,这个便不太确定了,这个故事发生在与UED迁移全局样式的过程. 曾经我有一段实现弹出层隐藏动画的代码是这个样子的: if (this ...
- Asp.net 后台添加CSS、JS、Meta标签
Asp.net 后台添加CSS.JS.Meta标签的写法,我这里写成函数方便以后使用.如果函数放在页面类中, Page参数也可以不要. 首先导入命名空间 using System.Web.UI.Htm ...
- django 关于html、css、js 目录位置
项目目录: project/ ---------------init.py ---------------views.py ---------------settings.py ----------- ...
- CI模板加载css和js
1.需求 ci无法加载css和js文件. 2.解决 删除..htaccess文件. 在config目录下配置base_url,并传给页面 $base_url = $this->config-&g ...
- HTML、CSS、JS对unicode字符的不同处理
unicode字符的不同表示法 unicode字符在html.css和js中的表示方法均不相同,下面分别作介绍. 原文发表于这里 css表示法 首先来一段很常见的bootstrap的字体图标代码: . ...
- 关于webStrom-11.1配置less且自动生成.css和自动压缩为.min.css/.min.js
网上看过很多配置思路,自己总结了以下, 就把我个人配置的顺序以及材料分享下,webstrom以下简称WB 1.配置less需要安装nodejs,自行安装.因为要用到npm.我是直接把npm解压到C盘根 ...
随机推荐
- RStudio中有常用的快捷键
1.常用快捷键 转自:https://blog.csdn.net/swuteresa/article/details/8649067 2.RStudio中如何撤销上一步操作: 一般运行过的程序都会在H ...
- windows10安装ubuntu18.04(64位)双系统教程
系统安装教程链接:https://www.cnblogs.com/masbay/p/11627727.html 系统安装完成后安装显卡驱动:https://ywnz.com/linux/4573.ht ...
- Java中String,JSON对象,java实体类(Bean)之间的相互转换
FastJson对于json格式字符串的解析主要用到了一下三个类: (1)JSON:fastJson的解析器,用于JSON格式字符串与JSON对象及javaBean之间的转换. (2)JSONObje ...
- LeetCode 删除数组中重复项 26 80
26(80) 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素只出现一次(使得出现次数超过两次的元素只出现两次 ) ,返回删除后数组的新长度.元素的 相对顺序 应该保 ...
- ansible使用笔记:长期更新
ansible使用笔记 ##将/home/system.sh文件拷贝到所有服务器的/home/system.sh ansible all -m copy -a "src=/home/syst ...
- Python 使用json存储数据
一.前言 很多程序都要求用户输入某种信息,如让用户存储游戏首选项或提供要可视化的数据.不管专注的是什么,程序都把用户提供的信息存储在列表和字典等数据结构中.用户关闭程序时,你几乎总是要保存他们提供的信 ...
- MyBatis面试题汇总
1.什么是Mybatis? Mybatis是对象关系映射一个框架,它内部封装了JDBC,开发的时候只要关注SQL语句本身,可以严格控制sql的执行性能,灵活,其二可以通过XML或者注解来配置映射信息 ...
- php curl 模拟post提交
/** * PHP发送Json对象数据 * @param $url 请求url * @param $jsonStr 发送的json字符串 * @return array */public functi ...
- swoft-个基于 Swoole 原生协程的PHP 微服务框架
刚才百度了一下swoft框架,官网打不开了,仓库也暂停了.不由感慨.曾经和同事踩了许多坑使用此极其小众的框架完成微服务项目.使用它的唯一目的就是提高程序性能(底层使用了协程),为此大家都学习了很多新知 ...
- 龙中华著《Spring Boot实战派》读书笔记之入门篇
第一章 进入Spring Boot的世界 理念:默认大于配置.有很多集成好的方案,开箱即用.针对痛点:环境配置耗时. 1.1 Spring Boot 的特色: 使用简单 注解方式实现类的定义和功能开发 ...