发布时间:2024年5月28日
随着单页应用成为前端开发的主流模式,页面之间原有的通过不同 html 资源实现样式隔离的方法不复存在,但随着组件化开发的深入,组件间样式干扰的问题也越来越频繁,前端行业开始寻找新的方法来管理样式,以适应更复杂的项目架构和开发流程。
在这个过程中,先后出现了以下几种解决方案:
作为最新阶段的产物,CssInJS 解决了前面几个阶段未能完全解决的问题:
下面介绍几个不同的 CssInJS 的前端库以及他们的心智模型
styled-components
是目前最受欢迎(也是特别早推出)的 CssInJS 库之一,也是是目前 Umi 框架推荐的方案,其允许用户通过模板字符串的方式书写样式,是 CSS 组件化的实现,其设计思路 —— 按照组件的方式写 CSS。
在使用 styled-compoents
作为 CssInJS 方案的项目中,其项目中的页面构成将变成下面这样:
通过这样的代码组织,我们可以
styled-component 的主要劣势在于它把类名的生成完全放在运行时,如果页面中节点较多,比较容易出现性能问题
emotion
类似于 styled-components
,但它更加灵活,提供了两种写法:对象样式和字符串模板样式。除此之外,emotion
最大的优势在于在不使用动态样式的场景下,其类名都是在编译时生成的,天然具有高性能特性(当然,成本不会消失只会转移)
emotion
方案的缺点有:
transform
问题,需要对打包工具进行额外配置import { css } from '@emotion/react';
import styled from '@emotion/styled'
// use template css
const CommonText = css`
color: rgba(0 0 0 / 85%);
font-size: 14px;
@media(min-width: 420px) {
color: #000;
}
&:hover {
opacity: 0.9;
}
`
// use object style
const CommonText = css({
color: 'rgba(0 0 0 / 85%)',
fontSize: 14,
'@media(min-width: 420px)': {
color: #000,
}
'&:hover': {
opacity: 0.9,
}
})
<p css={CommonText}>Text</p>
// use styled
const CommonText = styled.p`
color: rgba(0 0 0 / 85%);
font-size: 14px;
@media(min-width: 420px) {
color: #fff;
}
`
<CommonText>Text</CommonText>
// css array
const BoldStyle = css`
font-weight: 500;
`
<p css={[CommonText, BoldStyle]}>Bold Style</p>
// composition
const BoldText = css`
${CommonText};
${BoldStyle};
`
<p css={BoldText}>Bold Style</p>
// dynamic props
const DynamicBox = styled.div({
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeact'
}, (props) => {
return {
backgroundImage: `url(${props.imageUrl})`
}
})
<DynamicBox backgroundImage="xxxxxx">动态盒子</DynamicBox>
JSS
是最早推出的 CssInJS 的方案,但目前已经处于维护阶段,其也提供了两种实现逻辑:
react-jss
库提供的 hook + css object
用法styled-jss
库提供的 Component 类写法JSS 最有代表性的是其插件系统,比如 compose、global、nested 等均是通过插件实现的,但也因为配置复杂导致上手成本较高
从整体去看当前的 CssInJS 方案,可以简单的发现:
文档里提到的几种方案都提供了足够的灵活性供我们选择,从社区来看像 emotion / stylex
这类编译时方案正在成为主流的选择
CssInJS 作为一种 CSS 编写范式,除了会面对来自其他方案的竞争外,其存在的意义也一直在受挑战,尽管存在争议,但其确实为前端界带来了新的思考和解决方案。