antd Icon 组件

244 阅读1分钟

众所周知,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,另外两个包可自行做平替方案。

@loadable/component   classNames  tailwindcss