在 React 中为 className
自动添加 clsx,无需导入和编写,享受同样的乐趣。
值得注意的是,该库支持使用 Typescript
项目。目前尚未发现其他同类库可以做到这一点。
在执行此操作之前,请确保已安装 clsx 或项目存在其他可用的
className
处理程序。
npm
npm i babel-plugin-clsx -D
yarn
yarn add babel-plugin-clsx -D
pnpm
pnpm add babel-plugin-clsx -D
添加 babel 配置
{
"plugins": ["clsx"]
}
您的代码
<div className={['c1', 'c2']} />;
<div className={{ c1: true, c2: true }} />;
编译之后
import _clsx from 'clsx';
<div className={_clsx('c1', 'c2')} />;
<div className={_clsx({ c1: true, c2: true })} />;
options.[ static
| strict
| importSource
| importName
]
interface Options {
/**
* @default true
*/
static?: boolean;
/**
* @default true
*/
strict?: boolean;
/**
* @default 'clsx'
*/
importSource?: string;
/**
* @default 'default'
*/
importName?: string;
}
默认情况下,启用静态模式,该模式下仅转换 array
和 object
,有效避免了 className
的重复处理。当然,虽然不建议这样做,但你仍然可以关闭此选项,此后,由你来处理或忽略不必要的转换。
添加 babel 配置
{
"plugins": [
[
"clsx",
{
"static": false
}
]
]
}
您的代码
const className = ['c1', 'c2'];
<div className={className} />;
编译之后
import _clsx from 'clsx';
const className = ['c1', 'c2'];
<div className={_clsx(className)} />;
在现有的项目中,可能有很多这样的代码,如果关闭静态模式,就会有很多重复。
您的代码
import classNames from 'clsx';
// 👎 这将重复该过程
const className = classNames('c1', 'c2');
<div className={className} />;
// 👍 这并不重复过程
<div className={classNames('c1', 'c2')} />;
编译之后
import _clsx from 'clsx';
import classNames from 'clsx';
// 👎 这将重复该过程
const className = classNames('c1', 'c2');
<div className={_clsx(className)} />;
// 👍 这并不重复过程
<div className={classNames('c1', 'c2')} />;
严格模式默认是开启的,如果你想要为任意以 className
为后缀的属性添加 clsx,可以关闭该模式。
添加 babel 配置
{
"plugins": [
[
"clsx",
{
"strict": false
}
]
]
}
您的代码
<Component
className={['c1', 'c2']}
headerClassName={['c1', 'c2']}
footerClassName={['c1', 'c2']}
/>
编译之后
import _clsx from 'clsx';
<Component
className={_clsx('c1', 'c2')}
headerClassName={_clsx('c1', 'c2')}
footerClassName={_clsx('c1', 'c2')}
/>;
clsx 是默认支持的库,如果您有其他选择,你可以用 importSource
替换它。
添加 babel 配置
{
"plugins": [
[
"clsx",
{
"importSource": "classnames"
}
]
]
}
您的代码
<div className={['c1', 'c2']} />
编译之后
import _clsx from 'classnames';
<div className={_clsx('c1', 'c2')} />;
如果您的自定义导入源没有可用的默认导出,您可以使用 importName
指定导入名称。
添加 babel 配置
{
"plugins": [
[
"clsx",
{
"importSource": "@/utils",
"importName": "classNames"
}
]
]
}
您的代码
<div className={['c1', 'c2']} />
编译之后
import { classNames as _clsx } from '@/utils';
<div className={_clsx('c1', 'c2')} />;
如果您觉得有不必要的转换,可以添加注释,以便在转换过程中忽略它。
您可以通过在上面添加注释来忽略此行的转换。
您的代码
<div className={['c1', 'c2']} />;
<div
// @clsx-ignore
className={['c1', 'c2']}
/>;
编译之后
import _clsx from 'clsx';
<div className={_clsx('c1', 'c2')} />;
<div className={['c1', 'c2']} />;
您可以通过在文件顶部添加注释来省略整个文件的转换。
您的代码
// @clsx-ignore-global
<div className={['c1', 'c2']} />;
<div className={['c1', 'c2']} />;
编译之后
<div className={['c1', 'c2']} />;
<div className={['c1', 'c2']} />;
通过 jsxImportSource 支持 Typescript
。
只需要对tsconfig.json
进行少量修改,即可支持在Typescript
项目中使用该插件。
由于使用了高级语法,仅支持 react17+
和 Typescript4.7+
。
preserve
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "babel-plugin-clsx/jsx",
"isolatedModules": true
}
}
react-jsx
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "babel-plugin-clsx/jsx"
}
}
or
{
"compilerOptions": {
"jsx": "react-jsx",
"paths": {
"react/jsx-runtime": [
"./node_modules/babel-plugin-clsx/jsx/jsx-runtime.d.ts"
]
}
}
}
react-jsxdev
{
"compilerOptions": {
"jsx": "react-jsxdev",
"jsxImportSource": "babel-plugin-clsx/jsx"
}
}
react-native
{
"compilerOptions": {
"jsx": "react-native",
"jsxImportSource": "babel-plugin-clsx/jsx",
"isolatedModules": true
}
}
需要注意的一点是,
babel-plugin-clsx/jsx
仅支持类型推断,这会阻止Typescript
抛出错误。