Skip to content

🧰icon-component

icon 组件封装

🤓关键代码:

tsx
import { CSSProperties, forwardRef, PropsWithChildren, SVGAttributes } from "react";
import cs from 'classnames'
import './index.scss'

type BaseIconProps = {
    className?: string;
    style?: CSSProperties;
    size?: string | string[];
    spin?: boolean;
};

export type IconProps = BaseIconProps & Omit<SVGAttributes<SVGElement>, keyof BaseIconProps>;

export const getSize = (size: IconProps['size']) => {
    if(Array.isArray(size) && size.length === 2) {
        return size as string[];
    }

    const width = (size as string) || '1em';
    const height = (size as string) || '1em';

    return [width, height];
}

export const Icon = forwardRef<SVGSVGElement, PropsWithChildren<IconProps>>((props, ref) => {
    const {
        style,
        className,
        size = '1em',
        spin,
        children,
        ...rest
    } = props

    const [width, height] = getSize(size);

    const cn = cs(
        'icon',
        {
            'icon-spin': spin
        },
        className
    )

    return (
        <svg ref={ref} className={cn} style={style} width={width} height={height} fill="currentColor" {...rest}>{children}</svg>
    )
})

其中 index.scss 文件中实现 icon spin 等样式

创建 icon 组件,接收 svg

😎关键代码:

tsx
import { forwardRef, ReactNode } from "react";
import { Icon, IconProps } from ".";


interface CreateIconOptions {
    content: ReactNode;
    iconProps?: IconProps;
    viewBox?: string;
}

export function createIcon(options: CreateIconOptions) {
    const { content, iconProps = {}, viewBox = '0 0 1024 1024' } = options;

    return forwardRef<SVGSVGElement, IconProps>((props, ref) => {
        return <Icon ref={ref} viewBox={viewBox} {...iconProps} {...props}>{content}</Icon>
    })
}

支持从iconfont中创建icon图标

还是关键代码😋:

tsx
import { forwardRef } from "react";
import { Icon, IconProps } from ".";

const loadedSet = new Set<string>()

export function createFromIconfont(scriptUrl: string) {
    if (
        typeof scriptUrl === 'string'
        && scriptUrl.length
        && !loadedSet.has(scriptUrl)
    ) {
        const script = document.createElement('script');
        script.setAttribute('src', scriptUrl);
        script.setAttribute('data-namespace', scriptUrl);
        document.body.appendChild(script);

        loadedSet.add(scriptUrl);
    }

    const IconFont = forwardRef<SVGSVGElement, IconProps>((props, ref) => {
        const { type, ...rest} = props;

        return (
            <Icon ref={ref} {...rest}>
                {type ? <use xlinkHref={`#${type}`}/> : null}
            </Icon>
        )
    })

    return IconFont;
}

🔗🔗代码仓库

上次更新于: