本文介绍如何在React项目中使用CSS in JS方案:emotion。
emotion
emotion是一种高性能且灵活的CSS-in-JS库。它本身与框架无关,你可以在vue或者react中搭配使用。目前我们使用的是react,已经有多个项目在生产环境稳定运行。emotion11是对emotion10的略微改进,主要侧重于开发者的体验,TS的类型改进,以及使用新版本的解析器:Stylis。
本文主要介绍在React和TypeScript中如何集成emotion11。
变化
包重命名
emotion11最重要的变化之一是大部分面向用户的package都已经重命名。
重命名包的列表:
- @emotion/core → @emotion/react
- emotion → @emotion/css
- emotion-theming → moved into @emotion/react
- emotion-server → @emotion/server
- create-emotion → @emotion/css/create-instance
- create-emotion-server → @emotion/server/create-instance
- babel-plugin-emotion → @emotion/babel-plugin
- eslint-plugin-emotion → @emotion/eslint-plugin
jest-emotion → @emotion/jest
Hooks
在内部使用钩子以优化包的大小并在React DevTools中展示更好的DOM树。
TypeScript
TypeScript 类型已经被完全重写。
- 减少使用emotion时的构建时间,尤其是在大型项目中。
- 在许多情况下,不再需要为emotion组件手动指定通用参数
- 作为props的联合类型得到了更好的支持,应该正确推断
- 限制了css函数以防止传递无效的类型
- styled 的通用参数已更改,如果您指定ComponentType,则需要删除该通用参数
- styled不再需要第二个参数ExtraProps,代替地将其移动至styled调用之后。因此,styled
(MyComponent)应该被改写为styled(MyComponent) ({})
Theme类型
现在,为主题提供类型更加容易。您可以像这样创建内置的Theme接口,而不是像以前那样创建自定义实例:
import '@emotion/react' |
css prop 类型
基于使用的不同JSX运行时,emotion11为css prop提供TypeScript支持的方式已经更改,可以仅对支持className prop的组件添加对应css prop的支持(因为emotion的JSX工厂函数采用提供的css prop,对其解析并将生成的className传递给渲染的组件)。
Stylis V4
emotion使用的css解析器Stylis得到了升级,它修复了一些长期存在的解析边缘情况,同时变得更小,更快。
Emotion的缓存
创建高速缓存的自定义实例时,现在需要key选项。请确保它是唯一的(并且不等于“ css”),因为它用于将样式链接到缓存。如果多个缓存共享同一个键,它们可能会为彼此的样式元素“争斗”。 新的prepend选项可以使Emotion在指定DOM容器的开头而不是结尾处添加样式标签。
使用
安装
yarn add @emotion/react |
使用
// this comment tells babel to convert jsx to calls to a function called jsx instead of React.createElement |
css prop
emotion提供主要的书写style的方式是使用css prop,它提供了一个简洁灵活的API来对组件进行样式设定。
有两种方式使用css prop:
Babel Preset
Babel预设可在使用classic JSX运行时时自动启用Emotion的css prop。如果要使用新的JSX运行时,请不要使用此预设,而应使用@emotion/babel-plugin
- 安装
yarn add @emotion/babel-preset-css-prop |
- 使用
.babelrc{
"presets": [
[
"@emotion/babel-preset-css-prop",
{
"autoLabel": "dev-only",
"labelFormat": "[local]"
}
]
],
}
如果您使用兼容的React版本(>=16.14.0),则可以通过以下配置选择使用新的JSX运行时:
.babelrc{
"presets": [
[
"@babel/preset-react",
{ "runtime": "automatic", "importSource": "@emotion/react" }
]
],
"plugins": ["@emotion/babel-plugin"]
}
JSX Pragma
在使用CSS prop的源文件顶部设置jsx编译指示。此选项最适合测试css prop功能或在无法配置babel配置的项目(create-react-app,codesandbox等)中。
/** @jsx jsx */ |
与包含linter配置的注释类似,此配置将jsx babel插件配置为使用jsx函数而不是React.createElement。
如果您正在使用零配置工具来自动检测应该使用哪个运行时(classic还是automatic),并且您已经在使用具有新JSX运行时的React版本(因此运行时为您自动配置了runtime: ‘automatic’),例如Create React App 4,然后/ ** @jsx jsx * /
编译指示可能不起作用,您应该使用/** @jsx jsx */
import { jsx } from '@emotion/react'
。
使用css prop
/** @jsx jsx */ |
主题
Theme包含在@ emotion / react包中。
将ThemeProvider添加到应用程序的顶层,并在样式化组件中使用props.theme来访问主题,或者提供一个接受该主题作为css prop的函数。
使用
css function
import { ThemeProvider } from '@emotion/react' |
useTheme hook
import { ThemeProvider, useTheme } from '@emotion/react' |
类型
主题的类型需要在类型文件中声明,否则TS类型会报错。
types/emotion.d.ts
import "@emotion/react"; |
tsconfig.json
{ |
总结
CSS in JS的方案使用下来相比传统的less、sass等优点的确不少,而emotion的类似方案也有很多,对我感受最深的一点是,打包速度提升很多,没有冗余的CSS出现,但是对于习惯了css写法的人来说还是需要时间熟悉,总之,不妨一试。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章