Ant Design StyleAnt Design Style
快速上手
最佳实践
API
更新日志
⌘ K

Table of Contents

对比基础:原有的 V4 CSS Modules
1. styled 写法
2. css props 写法
3. css 配合 className 写法
各写法方案的对比小节
基础知识
简介
CSS in JS 快速入门
CSS in JS 写法对比
设计理念与实施策略
快速上手
书写样式
切换主题
自定义主题
进阶使用
Babel 插件
SSR 集成
组件研发
集成 styled
🚧 stylish 复合样式
CSSinJS 样式库性能对比
从 Less 迁移
Less 应用自动化迁移
Less 应用手动迁移
Less 组件迁移
🚧 CSSinJS 与 Less 的编译差异
上一篇
CSS in JS 快速入门
下一篇
设计理念与实施策略

相关资源

Ant Design
Ant Design Pro
Ant Design Pro Components
Umi-React 应用开发框架
Dumi-组件/文档研发工具
qiankun-微前端框架

社区

Medium
Twitter
yuqueAnt Design 语雀专栏
Ant Design 知乎专栏
体验科技专栏
seeconfSEE Conf-SEE Conf-蚂蚁体验科技大会

帮助

GitHub
更新日志
讨论

more products更多产品

yuque语雀-知识创作与分享工具
AntVAntV-数据可视化解决方案
EggEgg-企业级 Node.js 框架
kitchenKitchen-Sketch 工具集
xtech蚂蚁体验科技
Copyright © 2022-2024
Made with ❤️ by 蚂蚁集团 - AFX & 数字科技
‌
‌
‌
‌

CSS in JS 写法对比

由于 CSS in JS 的写法过多,所以我们需要给出一种最佳实践的写法,能兼容 V5 的 Token System、自定义主题、较低的研发心智和良好的扩展性。而本文会从各个角度来聊聊不同写法之间的差异。并给出 antd-style 最推荐的方式。

对比基础:原有的 V4 CSS Modules

我们先来回顾一下在之前(antd v4)的写法,这是我们与 CSS in JS 写法的对比基础。

大部分应用一旦使用 antd,一般都会搭配 less 和 css modules 来书写样式。页面书写的样式方案如下:

less
tsx

1. styled 写法

styled 的写法从体感上看完全是另一套代码。 由于我们在业务中已经持续使用了两年,所以相对来说经验也算丰富。先来讲讲使用 styled 的一些痛点。

首先,开发者需要重新学习 styled 的基础语法和相关的使用方式。并且如果使用 antd v4 less 的项目,要迁移到这种写法,基本上和重写没有区别。

在实际项目研发上,我们经历最痛的地方主要在于组件样式的覆写。 譬如需要对 antd 的 Button 进行样式覆盖,需要这么写:

tsx

这种覆盖方式对于设计完备的组件库来说,会极大地破坏代码的语义化。一旦以这种方式进行铺开,那么以后大家再也分不清代码中到底哪个 Button 组件才是 antd 的 Button。接手不同项目的研发心智成本会极大提升。

此外, Modal、Drawer 这样的组件存在多个 className 的情况,styled 由于写法的局限性是无法覆盖到的。因为 styled 包裹的组件默认只会把样式插入到 className 上,而像 Drawer 这种存在 rootClassName 的组件,要给 rootClassName 挂载样式会很困难。

最后,我们在实践中还会偶尔出现用 styled 包裹的 antd 组件,类型定义无法正常被提示出来,这也降低了研发效率。

讲完 styled 的缺点,再来说说 styled 的优势。

由于 styled 的写法可以保证每一个样式都能形成标准的 React 组件,且样式与样式之间的组合比较方便。因此,它非常适合制作一个从 0 开始建设的业务风格化组件库,或者制作一些具有统一风格的样式组件。

通过 styled 来声明一系列标准的样式组件,可以极大程度地减少重复的样式代码,并且帮助开发者形成明确的样式语义认知。详见案例:Typography 风格化组件

如果是在已有一个设计系统的基础上,styled 是不合适的。尤其是 antd v5 本身已经具有很强的动态主题能力基础之上。

2. css props 写法

这种写法似乎是 emotion 推荐的方案,而且 emotion 的核心维护者在自己的业务中也大量使用这种写法(详见:Why We're Breaking Up with CSS-in-JS)。这种写法存在两个很大的问题:1)样式代码耦合 ,2)性能缺陷。

css props 的写法会让样式代码直接与逻辑代码直接耦合在了一起,这样会导致样式代码的可维护性降低,而且在代码中难以区分出哪些是样式代码,哪些是逻辑代码(如下所示)。

tsx

这对于代码的可维护性来说是个灾难。 但如果是样式和逻辑代码分离,则清晰易懂(如下所示):

tsx

emotion 的前维护者在自己的业务中大量使用这种写法,但是他也在自己的博客 中提到了这种写法的问题:性能缺陷。

由于 react 的渲染机制, 将样式对象直接传入 css 属性时,由于每次渲染都会将 object 作为一个新对象处理,因此会造成 react 的 re-render,这样就会造成不必要的性能开销。而作者推荐的用法是,将 css props 中的对象放到组件外部静态化。但同时这样也就失去了 css-in-js 的动态化能力。

tsx

在迁移成本上,这种写法比 styled 稍微好一些,至少不需要额外定义组件,但是还是需要动组件中的 DOM 代码,并且需要引入 @emotion/react 的 jsx 对象,迁移成本还是高了一些。

3. css 配合 className 写法

css 配合 className 写法,是体感上非常简单的写法,同时也是这几种方案里面最容易迁移的写法。但 css 直接配合 className 的方案,还是存在一些问题:

纯 css 创建静态样式的方案,无法搭配使用 antd 的 token,也就不能享受到 css-in-js 的动态化能力。

而使用动态化能力,必须要使用 hooks 的方式,如下所示。

tsx

这样的写法,一方面每个函数都需要手动使用 theme.useToken 获取 token,量级一大非常麻烦,另一方面 hooks 返回的对象每次都会重新创建,因此一定会造成不必要的 re-render,如果每个 return 都包一下 useMemo,那么代码量还会更大。最后,再如果叠加自定义主题、动态主题等,这种写法就会变得非常复杂和啰嗦,包含一堆不要的代码。

各写法方案的对比小节

结合上述写到的几种方式最终整理,而 antd-style 希望再各项指标上做到最优,成为基于 antd 进行应用样式研发的最佳实践。

学习成本动态化能力自定义主题难度样式开发心智组件覆写心智性能迁移成本
CSS Modules✅ 无❌ 无❌ 难✅ 低✅ 低✅ 最优✅ -
styled⭕️️ 高✅ 高⚠️ 一般✅ 低⭕️️ 高✅ 优⭕️️ 高
css props⚠️ 中✅ 高⚠️ 一般⚠️ 高✅ 低⭕️️ 差⚠️ 中
css + className✅ 低✅ 高⚠️ 一般⚠️ 高✅ 低⭕️️ 中到差✅ 低
antd-style✅ 低✅ 高✅ 低✅ 低✅ 低✅ 优✅ 低