一个基于 Iconfont 自动生成 React/Vue 组件的 CLI 工具,免除字体依赖,提供多种实现方式,支持 TaroJS 和 UniApp。
- 字体文件方式 每次修改后需重新下载并替换字体文件和 CSS,过程繁琐。
- 在线 JS 引用方式 Symbol 字体图标的在线 JS 方式无法兼容小程序环境。
- 自动化:仅需简单配置,快速生成组件。
- 类型支持:内置类型定义,即使你不使用 TypeScript 也能获得良好的开发体验。
- 小程序兼容:完整支持小程序平台(TaroJS、Uni-App)。
- 可扩展性:支持自定义调整,灵活满足需求。
- 组件预览:具名导出便于预览组件效果(如下图所示)。
- 复制你的 Symbol 字体图标的在线 JS 链接(确保可以访问)
- 运行命令
npx @zd~/iconfont-cli@latest
- 根据命令提示完成你的配置
- 输入 Symbol 字体图标的在线 JS 链接
- 选择一个框架(React/Vue)
- 是否使用ts (yes / no)
- 请选择图标实现方式 (mask/background)
- 设置 Iconfont 组件路径文件夹(默认 src/components/iconfont)
- 是否具名导出每一个图标组件 (仅 React 可用)
- 设置具名导出组件的组件前缀(仅 React 可用)
配置完成后,工具会在当前目录下生成一个 iconfont-cli-config.json 文件,内容示例如下:
{
"jsLink": "//at.alicdn.com/t/c/你的链接.js", // Symbol字体图标的在线js链接
"framework": "react", // 框架
"useTs": true, // 是否使用 ts
"achieve": "mask", // 实现方式 mask 遮罩 或 background 背景图
"iconfontPath": "src/components/iconfont", // Iconfont 组件路径文件夹
"set": true, // 是否具名导出每一个图标组件 (仅 react 可用)
"iconPrefix": "icon" // 具名导出组件的组件前缀 (仅 react 可用)
}- 生成组件文件
工具会在 src/components/iconfont 目录下生成相应的组件文件,并提示操作成功。
生成的示例以上面配置为例
src/components/iconfont/iconfont-data.ts
/** * 图标 svg 数据 */ const iconfontData = { loading: '...', left: '...', // ... }
src/components/iconfont/iconfont-set.tsx
import { ComponentProps } from 'react' import { Iconfont } from '.' type CommonIconfontProps = Omit<ComponentProps<typeof Iconfont>, 'name'> /** * IconLoading iconfont component wrapper * *  */ export function IconfontLoading(props: CommonIconfontProps) { return <Iconfont name="loading" {...props} /> }
src/components/iconfont/iconfont-types.ts
/** * 图标名称 */ export type IconfontTypes = 'loading' // ....
src/components/iconfont/iconfont.tsx
import type { CSSProperties, HTMLAttributes } from 'react' import type { IconfontTypes } from './iconfont-types' import clsx from 'clsx' import { useMemo } from 'react' import data from './iconfont-data' interface IconfontProps extends HTMLAttributes<HTMLDivElement> { size?: number color?: string name: IconfontTypes } export function Iconfont({ size, color = '#000000', name, style, className, ...rest }: IconfontProps) { const mask = useMemo(() => { return `url("data:image/svg+xml;charset=utf-8,${encodeURIComponent(data[name])}")` }, [name]) const innerStyle = useMemo(() => { const _size = size ? `${size}px` : '1em' return { ...style, 'width': _size, 'height': _size, 'display': 'inline-block', 'maskImage': mask, // eslint-disable-next-line ts/ban-ts-comment // @ts-expect-error '-webkit-mask-image': mask, 'mask-size': _size, '-webkit-mask-size': _size, 'backgroundColor': color, 'maskRepeat': 'no-repeat', '-webkit-mask-repeat': 'no-repeat', } satisfies CSSProperties }, [mask, color, size, style]) return ( <div className={clsx('iconfont', className)} style={innerStyle} {...rest} > </div> ) }
- 更新在线图标
更新在线图标后,只需再次运行以下命令即可同步更新:
npx @zd~/iconfont-cli@latest
- 推荐脚本配置
为方便使用,可以将以下命令添加到项目的 package.json 中:
{
"scripts": {
"update-iconfont": "npx @zd~/iconfont-cli@latest",
"update-iconfont:force": "npx @zd~/iconfont-cli@latest --force"
}
}-
组件文件(React:
iconfont.jsx或iconfont.tsx,Vue:iconfont.vue)默认只会创建一次。这样设计的目的是支持用户自定义修改组件细节。例如,在小程序环境中,用户可以将
size单位调整为rpx,或修改组件的默认颜色。如果需要覆盖文件并重新创建,请使用以下命令:
npx @zd~/iconfont-cli@latest --force
-
实现方式
-
mask属性最早由 WebKit 于 2012 年引入,当时以-webkit-前缀存在。随后,在 2014 年,它被纳入了 CSS Masking Module Level 1 规范草案中。自 2023 年 12 月起,最新的设备和浏览器版本开始支持这一功能。然而,较旧的设备或浏览器可能无法使用此功能。值得注意的是,在微信小程序的 非 Skyline 渲染模式 下,mask 属性可以正常使用,而在 Skyline 渲染模式 下只能使用 background 属性。 -
相比于
mask属性,background属性的兼容性要更好。
-
感谢您的使用。如果你有任何问题或建议,请随时联系我。