关于css-in-js:为什么我们正在放弃-CSSinJS

这篇文章将深刻的开掘我过后为什么会在我的项目中应用 CSS-in-JS (本文应用 Emotion 计划 ),而当初为什么正在放弃这样的计划。 什么是 CSS-in-JSCSS-in-JS 容许你间接应用 JavaScript 或者 TypeScript 批改你的 React 组件的款式 import styled from '@emotion/styled'const ErrorMessageRed = styled.div` color: red; font-weight: bold;`;function App() { return ( <div> <ErrorMessageRed> hello ErrorMessageRed !! </ErrorMessageRed> </div> );}export default App;styled-components 和 Emotion 是 React 社区最风行的 CSS-in-JS 计划。本文中我只是提及到 Emotion ,然而我置信大部分的应用场景也同样实用于 styled-components。 本文专一于 运行时类型的 CSS-in-JS ,styled-components 和 Emotion 都属于这个类型。因为 CSS-in-JS 还有另一种类型,编译时类型 CSS-in-JS 这块会在文章末段略微提及到。 CSS-in-JS 的优缺点在咱们深刻理解 CSS-in-JS 的模式和它对性能的影响之前,咱们先从总体的理解一下为什么咱们会应用这项技术以及为什么要逐渐放弃 长处1.Locally-scoped styles: 当咱们在裸写 CSS 的时候,很容易就净化到其余咱们意想不到的组件。比方咱们写了一个列表,每一行的须要加一个内边距和边框的款式。咱们可能会写这样的 CSS 代码 ...

October 26, 2022 · 3 min · jiezi

material-ui中初探css in js

前期整了个个人博客系统,ui库也是变换了好几个,最后还是用上了material-ui。发现该ui库时居然没有像其他库一样引入css文件就可以显示,觉得很是神奇(选他只是觉得ui看的特别爽),后来才发现他样式是基于css in js的。简介发现material-ui的样式是基于css in js时,我很是想再换个ui库,毕竟用less、sass也是很不错的?况且,web发展这么久,好不容易把三大基本元素给拆分开了,现在又要合并起来,很是反感。不过,细细看了下,发现感觉还不错。如其表面意思一样,即是在js中写css样式,先不谈这么写的好处与坏处。想想我们平时写css的难处:命名难,起名很是怕冲突。样式覆盖问题(作用域)。比less,sass更灵活的编程语法。当然,这些问题在其他的像css module等方案中也是可以解决的。个人觉得,最后一点用的很是不错,将css逐步能推向编程语言的范畴。简单使用material-ui中使用的是jss库,我们尝试在react项目中使用他。react项目中要使用react-jss库,在create-react-app脚手架生成的代码中,修改App.js,import React, { Component } from ‘react’;import withStyles from ‘react-jss’;// 样式,使用colorBlue就对应后面的样式const styles = { colorBlue: { color:‘blue’ }};const Test = ({ classes }) => { return ( <span className={classes.colorBlue}>test</span> );};const StyledTest = withStyles(styles)(Test);class App extends Component { render() { return ( <div> <StyledTest></StyledTest> </div> ); }}export default App;3000端口的页面可以看到字体已经是蓝色的了,将所有的样式以样式名: 样式内容的方式写在styles对象之中,再用withStyles注入到组件之中(也可以使用injectSheet代替withStyles),其实使用上去还是不算太变扭。看下在浏览器中渲染的class名,命名很有规律,更多其他规律可以自己尝试下。那么在class方式定义的组件中怎么使用呢?忽略相同的import和styles的定义,看下组件的定义,@withStyles(styles)class App extends Component { render() { const {classes} =this.props; return ( <span className={classes.colorBlue}>text</span> ); }}export default App;不过很可惜,在create-react-app项目中,es7的修饰器是不支持的,提示Support for the experimental syntax ‘decorators-legacy’ isn’t currently enabled。我也找了好多中处理方法,都还是在报错,所以只能换种写法了,// @withStyles(styles)class App extends Component { render() { const {classes} =this.props; return ( <span className={classes.colorBlue}>text</span> ); }}export default withStyles(styles)(App);这下页面正常了。更多的用法可以查看他的官方文档。总结使用的时候又发现了个优点,生成的样式只适用于对应的页面,可以惰性加载,且没有冗余的样式代码。缺点肯定也是有的,又增加了学习成本。当在大型项目中使用时,不知道会不会乱起来。样式权重没了,覆盖成了问题,难道只能用important?没法和postcss一起使用。理念了解后,可以尝试下其他的css in js库,比如styled-component等等。留下项目地址:https://github.com/2fps/blooog 。个人博客地址:http://www.zhuyuntao.cn/2019/… ...

March 17, 2019 · 1 min · jiezi

2019年前端的3个趋势

简介:JavaScript 应用范围广泛,静态类型语言 TypeScript 会继续得到更多开发者的青睐。组件成为前端最基本的物料,CSS 融合在组件中(CSS in JS)的方案日趋成熟。前端的“端”越来越多, API 查询语言 GraphQL 会继续保持高速增长 。JavaScript 应用范围广泛,TypeScript 更受青睐在 github 2018 调查报告的中,JavaScript 连续多年稳居第一,成为最受欢迎的开发语言。从 Stack Overflow 的调查报告中,我们可以看到更详细的数据,任意两个开发者中至少有一个会 JavaScript,并且这个比例还在持续增长,从 2016年的 55.4%,到 2017年的 62.2% ,到 2018 年的 69.8%。在 npm 的调查报告中,JavaScript 生态圈也是非常繁荣,module 的数量继续保持高速增长,将其他语言远远的甩在了后面。图一: npm 2018 调研报告 - Module Counts从使用范围上看,JavaScript 可以写前端、服务端、移动端,甚至还可以写物联网应用。在 npm 2018 的调研报告中,大多数 JavaScript 开发者写 web 前端应用(93%)和 node.js 服务端应用(70%)。在 stateofjs 2018 的调研报告中,还有相当数量的 JavaScript 开发者写移动或桌面应用,例如 Electron(19.6%)、React Native(18.7%)、Native Apps(10.6%), Flutter 、Weex、PWA 都在 1% 以内。备注:npm 和 stateofjs 的调研用户群体特征类似,统一归类为 JavaScript 开发者。图二: npm 2018 调研报告 - The JavaScript I write runs on…值得注意的是,TypeScript 在 2018 年得到更多开发者的青睐。在 github 语言排行版中,TypeScript 上升了 3 名,排到了第 7 的位置。在 stateofjs 2018 的调研报告中, JavaScript 开发者有 86.3% 愿意继续使用 ES6,有 46.7% 愿意继续使用 TypeScript。排在第三、四的是 Facebook 的 Flow 和 Reason 语言,但是占比都不高。图三:stateofjs 2018 调研报告- JavaScript Flavors从互联网的发展历史的角度看,2010 年 3G (国内)开始普及,2014 年 4G 全面铺开,拉开移动互联网的序幕。互联网从传统的内容提供者,转变成了服务提供者。前端应用也发生的本质的转变,从传统互联网时代的内容展示,转变成了拥有复杂交互的逻辑的服务提供窗口。随着前端应用变得越来越复杂,和 JavaScript 应用的领域越来越广泛,传统 JavaScript(ES5) 已经适应复杂的开发需求,因此功能更加强大的 ES6 孕育而出。在 JavaScript 应用复杂度不断增加的背景下,预计 2019 年,静态类型语言 TypeScript 会继续得到更多开发者的青睐。TypeScript 属于 ES6 的超集,一方面它可以很好的兼容 ES6 语法,另一方面它又提供了可选的静态类型检查和接口(interface)的功能。在开发复杂度高、需要大规模合作的 JavaScript 应用时,TypeScript 相对 ES6 不妨是一种更好的选择。组件成为最基本的前端物料,CSS in JS 让组件化更彻底在 stateofjs 2018 的调研报告中, JavaScript 开发者有 64.8% 愿意继续 React,有 28.8% 愿意继续 Vue。但根据个人观察,在国内 Vue 开发者会比 React 多一些,这可能是因为 Vue 上手简单并且有完善的中文文档。Angular 方面,有超过一半使用 Angular 框架的开发者表示,不愿意继续使用 Angular 进行开发了。而其他开发框架 Preact、Ember、Polymer、JQuery 的使用量都很少。现在,React 和 Vue 已经成为前端开发框架的双雄,不会 React 或 Vue 可能连工作都不好找。图四:stateofjs 2018 调研报告 - Front-end Frameworks组件是 React 和 Vue 最强大的功能之一。在 Vue 中一个 .vue 文件就是一个组件,包含 Template、JS、CSS 三个部分,其中 CSS 部分是可选的,开发者也可以将 CSS 独立出去。在 React 中一个 .jsx 文件就是一个组件,但是 JSX 只能包含 Template、JS 两个部分,组件的 CSS 部分必须 import from ‘xxx.css’ 进来。无论是 React 还是 Vue,都改变不了 CSS 全局作用域的问题。开发者可以在一个组件中,通过 Selector,如 .class .id ,取到本该属于其他组件的 CSS 样式。组件本应是一个独立的作用域,但是它的 CSS 竟然是全局的!在应用复杂度低、单人开发的情况下 CSS 全局作用域不算大问题。但是在多人合作开发的场景下,可能会因此导致样式冲突。比如,因为引入了 B 开发者的组件,A 开发者的组件样式错乱了,这就导致了较高的联调成本。图五:CSS document level V.S. component level解决的思路就是,使用 CSS in JS 的工具,使得 CSS 只对它归属的组件生效。CSS in JS 的方案有很多,主流的有:styled-components、emotion、css-modules、aphrodite、glamor、glamorous、radium、react-jss。styled-components 方案使用人数最多,emotion 方案排第二并且增长势头凶猛,而 css-modules 方案在两年前已经停止维护了,不再推荐。styled-components 的写法太反直觉,个人更喜欢 emotion。从下载量的增长势头来看 emotion 比 styled-components 更快。因此,如果有 CSS in JS 需求的项目,更加推荐 emotion。相信在 2019 年,CSS in JS 方案会更加成熟,我们不妨期待吧。图六: npmtrends.com CSS in JS 方案下载量对比“端”越来越多,GraphQL 继续保持高速增长在移动互联网时代来临之前,传统意义上的前端只有浏览器的 PC 端。移动互联网兴起后,出现了浏览器的 H5 端、iOS 端、Android 端。再后来一些平台级 App ,比如微信、QQ,推出了自己的 JS-SDK,Hybird 也成为了新的端。近两年,微信、支付宝、百度、头条也推出了自己的小程序平台,小程序也成为了新的端。每个端都有自个儿的个性,不存在一种大统一的方案,可以适配所有的端。这导致了同一个业务,需要在 6 个端,开发 6 次、联调 6 次。我们假设有一个这样的 API,它包含了该业务在各个端上所有的数据,这不就解决了多次联调的问题了嘛。虽然还是需要开发 6 次,但是现在因为只有 1 个 API,所以联调次数变成了 1 次。但是该方案的背后的代价是,加载慢、维护成本高。任意 1 个端,都要获取其他 5 个端的上差异化的数据,加载能不慢嘛。如果 API 有改动,可能会影响到 6 个端的代码,维护起来也费劲。稍作改变,现在我们假设,前端可以通过一种标准的 API 查询语法,精确地获取任意自定义的数据,在服务端通过解析前端查询语句,返回其自定义的查询数据。虽然还是 6 个端,1 个 API,但是每个端可以只获取自己的数据,不就解决了加载慢的问题了嘛。如果某个端需要增改获取的数据,只需要修改这个端的查询语句即可,这不就解决了维护成本高的问题了吗。通过定义一种标准的 API 查询语法,可以使得前端获取 API 数据,就像从数据库获取数据一样方便和灵活。GraphQL 就定义一套标准的 API 查询语法,在保持灵活性和可维护性的前提下,极大的降低了联调成本。备注:GraphQL 官方使用的例子是,一个业务要请求多个 REST 规范的 API 。但是,国内通常使用的不是准守标准的 REST API ,他们的痛点在国内不那么痛,所以改用多端多 API 联调成本高来举例。图七:@helferjs 从REST到GraphQL因为使用 API 查询语言 GraphQL 获取的方法太简单了,所以连数据管理的事省了。也就是说,使用 GraphQL 可以把 Redux、Mobx 干的活给省了。我们可以看到,在 stateofjs 2018 调研报告中, 把 GraphQL 和 Redux、Mobx 都归类为一类 —— 数据层(Data Layer)。报告中指出,有 47.2% 的 JavaScript 开发者表示会继续使用 Redux,20.4% 会继续使用 GraphQL, 5.6% 会继续使用 Mobx。需要留意的是,有 62.5% 表示对 GraphQL 感兴趣,因此 GraphQL 获得 stateofjs 的最感兴趣奖(Highest Interest)。图八:stateofjs 2018 调研报告 - Data Layer预计 2019 年,GraphQL 会继续保持高速增长,被更多的开发者使用。在 npm 2018 调研报告中,特意指出了 GraphQL 的客户端库 Apollo 的下载量保持着高速的增长。图九:npm 2018 调研报告-GraphQL continues hyper-growth ...

January 4, 2019 · 2 min · jiezi

Css in Js 一次实践

最近需要做一个表格组件,组件需求:指定行、列可以跨行、跨列行和行之间有分割线最终采用grid实现需求。实现的时候遇到一个问题,如果css和js分开写,css只能是定值,没有灵活性。所以考虑采用css in js的形式。关于css in js相关的概念介绍可以参考阮一峰老师的文章:css in js 介绍。在github上找了一下关于这方面的组件,发现styled components 非常不错,简单易上手,npm下载:npm i styled-components -S注意:React < 16 需要下载3.x.x版本的 根据文档先写一个简单的demo。可以看到,它的实现方式并不是传统的以对象的形式写样式,而是将需要添加样式的元素加到styled对象上,然后跟一个(``)反引号标签,在里面以正常的css格式写样式。然后返回一个组件,把组件替换原来的div即可。实现效果:html代码:css代码:刚才我们添加样式的元素是html元素,那么给组件添加样式可以么?实践一下:const H1 = ({ className }) => <h3 className={className}>我是App</h3>;const HH = styled.H1 font-size: 30px; color: red;;运行,报错:咋回事?原来styled不支持以 . 符号的形式为组件添加样式,需要以参数形式传递,修改上面代码const HH = styled(H1) font-size: 30px; color: red;;将H1组件以参数形式传递给styled,就可以了。想给元素添加伪元素样式,子元素样式可以么?没问题,styled components支持样式嵌套,按照类似Less或Scss的书写方式就可以了。const Container = styled.div width: 300px; max-width: 500px; min-width: 200px; transition: all 1s ease-in-out; background-color: rgba(240, 240, 240, 0.9); ::after { content: 'after'; display: table; color: blue; } span { color: green; };以上我们写的组件都是在Class外面,那我们要根据props设定样式怎么办?styled components同样支持在Class内生成组件,并接受props传递过来的值,这个props并不是我们的Class接收的props,它是添加样式的元素上的Props,意思就是class Demo { render(){ return <Styled name=“guoshi”></Styled> }}Demo.defaultProps = { age: 18}const Styled = styled.p color: ${props=&gt;{console.log(props)}} // {name: "guoshi",theme:{...}}如果想使用Class的props怎么办?看代码:generateStyle = () => { const {row, col, justify, data, prefixCls, showborder = true, rowgap = 0, colgap = 0} = this.props; const child = []; data.map((item,index)=> (item.colSpan || item.rowSpan) ? child.push({index:index+1,colSpan:item.colSpan, rowSpan:item.rowSpan}):null); const bordernone = []; for(let i = 0; i < row; i++) { bordernone.push(1 + i*col); } const UlContainer = styled.ul.attrs({className: prefixCls}) display: grid; grid-template-columns: ${()=&gt; { let arr = []; arr.length = col; return arr.fill('1fr').join(' '); }}; grid-template-rows: ${()=&gt; { let arr = []; arr.length = row; return arr.fill('1fr').join(' '); }}; grid-gap: ${rowgap} ${colgap} ; justify-items: ${()=&gt; justify || "center"}; ::before { display: none; } li { width: 100% !important; } ${ child.map(({index, colSpan, rowSpan}) =&gt; li:nth-child(${index}) { grid-column-start: ${index%col === 0 ? index : index%col}; grid-column-end: ${colSpan ? (colSpan+(index%col === 0 ? index : index%col)) : ((index%col === 0 ? index : index%col)+1)} grid-row-start: ${Math.ceil(index/col)}; grid-row-end: ${rowSpan ? rowSpan+Math.ceil(index/col) : Math.ceil(index/col)+1}; align-items: start; } ).join(' ') } li + li { border-left: 1px dashed rgba(0,0,0,0.3); } ${ bordernone.map(bordernoneindex=&gt; li:nth-child(${bordernoneindex}) { border-left: none; } ).join(' ') } ; return UlContainer; }提前把最后代码放出来了,styled.ul.attrs({})就是为元素添加额外的属性,比如className、placeholder等,从代码中可以看到,无论是Class的props还是元素自身传进来的props,styled都可以接收,你可以自定义任何你想实现的规则,更方便我们配置的灵活性。其实到这里,使用上没有任何问题了,关于keyframes等规则官网上都有demo,也非常容易实现。想尝试的小伙伴现在就可以码一遍。不过本章遗留了很多问题:styled.div & styled(div) 有什么区别模版字符串中的样式是怎么解析的?为什么可以嵌套?为什么会返回一个组件?下一章,我会根据styled componnets源码解答上述问题。最后,祝生活愉快。 ...

December 28, 2018 · 2 min · jiezi

css-in-js 探讨

Web开发是需要掌握多种技术。我们习惯于与多种语言密切合作。而且,随着开发Web应用程序变得越来越普遍和差别细微化,我们经常寻找创造性的方法来弥合这些语言之间的差距,从而使我们的开发环境和工作流程更容易,更高效。最常见的示例通常是使用模板语言时。例如,可以使用一种语言来生成更详细的语言(通常是HTML)的代码。这是前端框架的关键作用之一 -操作HTML。这个领域最出名的就是JSX,因为它不是真正的模板语言;它是JavaScript的语法扩展,它使得使用HTML非常简洁。Web应用程序经历了许多状态组合,单独管理状态通常很有挑战性。这就是为什么CSS有时会被淘汰的原因 - 即使通过不同的状态和媒体查询管理样式同样重要且同样具有挑战性。在这个由两部分组成的系列中,我想将CSS放在聚光灯下,并探索弥合它与JavaScript之间的差距。在本系列中,我将假设您正在使用像webpack这样的模块解析器。因此,我将在我的示例中使用React,但相同或类似的原则适用于其他JavaScript框架,包括Vue。CSS领域正朝着多个方向发展,因为要解决许多挑战并且没有“正确”的路径。我一直在花费大量精力尝试各种方法,主要是在个人项目上,所以这个系列的目的只是告知,而不是给你解决方案。CSS的挑战在深入研究代码之前,有必要解释Web应用程序样式化方面最显着的挑战。 我将在本系列中讨论的是范围,条件和动态样式以及可重用性。作用域作用域定是众所周知的CSS挑战,它的目的是编写不会影响到组件外部的样式,从而避免意外的副作用。 我们希望在不影响编码体验的情况下实现功能。条件和动态样式虽然前端应用程序中的状态开始变得越来越先进,但CSS仍然是静态的。 我们只能有条件地应用样式集 - 如果按钮是主要的,我们可能会应用“primary”类并在单独的CSS文件中定义它的样式以应用它在屏幕上的样式。 有几个预定义的按钮变化是可管理的,但如果我们想要有各种按钮,如为Twitter,Facebook,Pinterest定制的特定按钮,可能还会有其他很多种? 我们真正想要做的只是传递颜色并使用CSS定义状态,如悬停,焦点,禁用等。这称为动态样式,因为我们不再在预定义样式之间切换 - 我们不知道接下来会发生什么。 可能会想到内联样式来解决此问题,但它们不支持伪类,属性选择器,媒体查询等。可重用性重用规则集,媒体查询等是我最近很少看到的一个主题,因为它已经被Sass和Less等预处理器解决了。 但是我仍然想在这个系列中再次提起它。我将列出一些处理这些挑战的技术以及它们在本系列的两个部分中的局限性。 没有任何技术优于其他技术,它们甚至不相互排斥; 您可以选择一个或组合它们,具体取决于您的决定是否能改善您的项目质量。开始吧我们将使用名为Photo的示例组件演示不同的样式技术。 我们将呈现可能具有圆角的响应式图像,同时将替代文本显示为标题。 它会像这样使用:<Photo publicId=“balloons” alt=“Hot air balloons!” rounded />在构建实际组件之前,我们将抽象出srcSet属性以保持示例代码简洁。 那么,让我们创建一个带有两个实用程序的utils.js文件,用于使用Cloudinary生成不同宽度的图像:import { Cloudinary } from ‘cloudinary-core’const cl = Cloudinary.new({ cloud_name: ‘demo’, secure: true })export const getSrc = ({ publicId, width }) => cl.url(publicId, { crop: ‘scale’, width })export const getSrcSet = ({ publicId, widths }) => widths .map(width => ${getSrc({ publicId, width })} ${width}w) .join(’, ‘)我们设置Cloudinary实例以使用Cloudinary的演示云名称,以及根据指定选项为图像publicId生成URL的url方法。 我们只对修改此组件的宽度感兴趣。我们将分别将这些实用程序用于src和srcset属性:getSrc({ publicId: ‘balloons’, width: 200 })// => ‘https://res.cloudinary.com/demo/image/upload/c_scale,w_200/balloons'getSrcSet({ publicId: ‘balloons’, widths: [200, 400] })// => ‘https://res.cloudinary.com/demo/image/upload/c_scale,w_200/balloons 200w, https://res.cloudinary.com/demo/image/upload/c_scale,w_400/balloons 400w’如果你不熟悉srcset和sizes属性,我建议先阅读一下有关响应式图像的内容。 这样,您可以更轻松地按照示例进行操作。CSS-in-JSCSS-in-JS是一种样式方法,它将CSS模型抽象到组件级别,而不是文档级别。 这个想法是CSS可以限定为特定组件 - 并且只限于该组件 - 以使这些特定样式不与其他组件共享或泄露到其他组件,并且仅在需要时才调用。 CSS-in-JS库通过在<head>中插入<style>标签在运行时创建样式。使用这个概念的第一个库是JSS。 以下是使用其语法的示例:import React from ‘react’import injectSheet from ‘react-jss’import { getSrc, getSrcSet } from ‘./utils’const styles = { photo: { width: 200, ‘@media (min-width: 30rem)’: { width: 400, }, borderRadius: props => (props.rounded ? ‘1rem’ : 0), },}const Photo = ({ classes, publicId, alt }) => ( <figure> <img className={classes.photo} src={getSrc({ publicId, width: 200 })} srcSet={getSrcSet({ publicId, widths: [200, 400, 800] })} sizes="(min-width: 30rem) 400px, 200px" /> <figcaption>{alt}</figcaption> </figure>)Photo.defaultProps = { rounded: false,}export default injectSheet(styles)(Photo)乍一看,样式对象看起来像用对象表示法编写的CSS,带有附加功能,比如传递一个函数来设置基于props的值。 生成的类是唯一的,因此您永远不必担心它们与其他样式冲突。 换句话说,你可以自由的使用作用域! 这就是大多数CSS-in-JS库的工作方式 - 当然,我们将在功能和语法方面进行一些改进。您可以通过属性看到渲染图像的宽度从200px开始,然后当视口宽度变为至少30rem时,宽度增加到400px宽。 我们生成了额外的800宽度,以覆盖更大的屏幕密度:1x screens 使用 200 and 4002x screens 使用 400 and 800styled-components是另一个CSS-in-JS库,但是使用更熟悉的语法巧妙地使用模板文字而不是对象看起来更像CSS:import React from ‘react’import styled, { css } from ‘styled-components’import { getSrc, getSrcSet } from ‘./utils’const mediaQuery = ‘(min-width: 30rem)‘const roundedStyle = css border-radius: 1rem;const Image = styled.img width: 200px; @media ${mediaQuery} { width: 400px; } ${props =&gt; props.rounded &amp;&amp; roundedStyle}; const Photo = ({ publicId, alt, rounded }) => ( <figure> <Image src={getSrc({ publicId, width: 200 })} srcSet={getSrcSet({ publicId, widths: [200, 400, 800] })} sizes={${mediaQuery} 400px, 200px} rounded={rounded} /> <figcaption>{alt}</figcaption> </figure>)Photo.defaultProps = { rounded: false,}export default Photo我们经常创建语义中性元素,如<div>和<span>,仅用于样式目的。这个库以及许多其他库允许我们在一个动作中创建和设置它们。我最喜欢这种语法的好处是它就像常规的CSS,减去插值。这意味着我们可以更轻松地迁移CSS代码,并且我们可以使用现有的css知识,而不必熟悉在对象语法中编写CSS。请注意,我们可以在我们的样式中插入几乎任何东西。此特定示例演示了如何将媒体查询保存在变量中并在多个位置重用它。响应式图像是一个很好的用例,因为sizes属性基本上包含CSS,所以我们可以使用JavaScript来使代码更简洁。假设我们决定在视觉上隐藏字幕,但仍然可以让屏幕阅读器访问它。我知道实现这一目标的更好方法是使用alt属性,但为了这个例子,让我们使用不同的方式。我们可以使用一个名为polished的样式mixin库 - 它适用于CSS-in-JS库,非常适合我们的示例。这个库包含一个名为hideVisually的mixin,它正是我们想要的,我们可以通过插入它的返回值来使用它:import { hideVisually } from ‘polished’const Caption = styled.figcaption ${hideVisually()};<Caption>{alt}</Caption>即使hideVisually输出一个对象,样式组件库也知道如何将其作为样式进行插值。CSS-in-JS库具有许多高级功能,如主题,供应商前缀甚至内联关键CSS,这使得完全停止编写CSS文件变得容易。 此时,您可以开始了解为什么CSS-in-JS成为一个诱人的概念。缺点和局限CSS-in-JS的明显缺点是它引入了一个运行时:需要通过JavaScript加载,解析和执行样式。 CSS-in-JS库的作者正在添加各种智能优化,如Babel插件,但仍然存在一些运行时成本。同样重要的是要注意PostCSS没有解析这些库,因为PostCSS不是设计用于运行时的。许多人使用stylis作为结果,因为它更快。这意味着我们遗憾的是无法使用PostCSS插件。我要提到的最后一个缺点是工具。 CSS-in-JS正在以非常快的速度发展,文本编辑器扩展,linters,代码格式化等等需要追赶新功能以保持同等水平。例如,人们正在使用VS Code扩展样式组件来表示类似情感的CSS-in-JS库,即使它们并非都具有相同的功能。我甚至看到提议功能的API选择受到保留语法突出显示的目标的影响!未来有两个新的CSS-in-JS库,Linaria和astroturf,它们通过将CSS提取到文件中来管理零运行时。 它们的API类似于样式组件,但它们的功能和目标各不相同。Linaria的目标是通过内置函数(如作用域,嵌套和供应商前缀)来模仿CSS-in-JS库的API,如样式组件。 相反,astroturf是基于CSS模块构建的,具有有限的插值功能,并鼓励使用CSS生态系统而不是使用JavaScript。结论CSS-in-JS是一体化的样式解决方案,用于弥合CSS和JavaScript之间的差距。 它们易于使用,并且包含有用的内置优化 - 但所有这些都需要付出代价。 最值得注意的是,通过使用CSS-in-JS,我们基本上从CSS生态系统中退出并使用JavaScript来解决我们的问题。零运行时解决方案通过恢复CSS工具来缓解一些缺点,这些工具将CSS-in-JS讨论提升到更有趣的水平。 与CSS-in-JS相比,预处理工具的实际限制是什么? 这将在本系列的下一部分中介绍。 ...

December 10, 2018 · 2 min · jiezi