众所周知,antd 支持 icon,类似于下面这种用法
import { StarOutlined } from '@ant-design/icons';
export default () => {
return (
<StarOutlined />
)
}
but, 如果我要通过配置化的方式使用,可能代码就得写成这样
import { StarOutlined, StarFilled } from '@ant-design/icons';
export default (props: { icon: string }) => {
const Icon = props.icon === 'StarOutlined' ? StarOutlined : StarFilled
return (
<Icon />
)
}
你要说不行,那也不是不行,但是呢,它不完美,不优雅……
神说要有光,于是就有了下面的组件 Icon
import { theme } from 'antd';
import { ReactNode } from 'react';
import loadable from '@loadable/component';
import { ColorMapToken } from 'antd/es/theme/interface/maps/colors';
import classNames from 'classnames';
const { useToken } = theme
const LoadableIcon = loadable(
(props: { icon: string }) => import(`@ant-design/icons/${props.icon}.js`),
{
cacheKey: (props) => props.icon
}
);
export default (props: {
icon?: string;
color?: keyof ColorMapToken;
size?: 'sm' | 'lg' | 'xl';
className?: string
}): ReactNode => {
if (!props.icon) {
return null
}
const { token } = useToken()
const size = props.size
const clz = classNames('inline-block', {
'*:text-sm': size === 'sm' || size === undefined,
'*:text-lg': size === 'lg',
'*:text-xl': size === 'xl'
}, props.className)
return (
<span className={clz} style={{ color: props.color ? token[props.color] : undefined }}>
<LoadableIcon icon={props.icon} />
</span>
)
}
将上面文件保存为 Icon.tsx 用法如下
import Icon from '@/components/Icon'
export default () => {
return (
<Icon icon="StarOutlined" size="lg" color="colorSuccess"/>
)
}
说完了用法,这里讲解一下,需要用的依赖包有 @loadable/component、classNames, 以及 tailwindcss, 其中动态加载就是利用了 @loadable/component,另外两个包可自行做平替方案。