SVG 转 JSX 转换器
在浏览器中即时将 SVG 转换为 React JSX 组件,自动处理驼峰属性、className,支持 TypeScript、forwardRef 和 memo 包裹。免费无需注册。
- 在浏览器中处理
- 数据不离开你的设备
- 免费 · 无需注册
用微信扫描以下二维码即可分享
示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。
属性转换规则
| SVG | JSX |
|---|---|
stroke-width | strokeWidth |
stroke-linecap | strokeLinecap |
fill-rule | fillRule |
clip-path | clipPath |
class | className |
font-size | fontSize |
text-anchor | textAnchor |
xmlns="..." | (已移除) |
输出模式
- 默认:无 TypeScript 注解的普通函数组件。
- TypeScript:添加
React.FC<React.SVGProps<SVGSVGElement>>类型,支持className、style、onClick等 prop。 - forwardRef:将组件包裹在
React.forwardRef中,向父组件暴露 SVG 元素的 ref。 - memo:将最终导出包裹在
React.memo中,跳过不必要的重新渲染。
常见使用场景
- 将 Figma 或 Illustrator 导出的 SVG 转换为 React 图标组件
- 将 SVG 图标库迁移到基于 JSX 的设计系统
- 让 SVG 图标接受
className、style等 React props - 构建通过展开 props 接受
aria-label的无障碍图标组件
示例
一个 24 × 24 的加号图标,组件名填 PlusIcon,三个选项都不勾:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="#000" stroke-width="2" stroke-linecap="round" d="M12 5v14M5 12h14"/></svg>
输出:
import React from 'react';
function PlusIcon(props) {
return (
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}><path stroke="#000" strokeWidth="2" strokeLinecap="round" d="M12 5v14M5 12h14" /></svg>
);
}
export default PlusIcon;
xmlns 被删掉,stroke-width、stroke-linecap 改成驼峰,其余标记原样保留。{...props} 放在根元素自身属性之后,与 svgr 的默认值(expandProps: 'end')位置相同,调用方传的值优先:<PlusIcon width={48} fill="red" /> 渲染成 48 px、红色,height 仍是 24。属性值仍是字符串(strokeWidth="2"),React 字符串和数字都接受。TypeScript、forwardRef、memo 全勾时,同一图标输出为 const PlusIcon = forwardRef<SVGSVGElement, React.SVGProps<SVGSVGElement>>(function PlusIcon(props, ref) { ... }),<svg> 自身属性之后是 ref={ref} {...props},末尾 export default memo(PlusIcon);。React 19 起不再需要 forwardRef,函数组件可以直接把 ref 当作 prop 接收。
Illustrator 用 Internal CSS 导出、带内联 style 与 xlink:href 的图标,组件名 Icon:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><!-- Generator: Adobe Illustrator --><defs><style>.cls-1{fill:#e11d48;}</style></defs><path id="a" class="cls-1" style="stroke:#000;stroke-width:2" d="M12 5v14"/><use xlink:href="#a"/></svg>
输出:
import React from 'react';
function Icon(props) {
return (
<svg viewBox="0 0 24 24" {...props}>{/* Generator: Adobe Illustrator */}<defs><style>{".cls-1{fill:#e11d48;}"}</style></defs><path id="a" className="cls-1" style={{ "stroke": "#000", "strokeWidth": "2" }} d="M12 5v14" /><use xlinkHref="#a" /></svg>
);
}
export default Icon;
注释变成 {/* ... */},React 不会渲染它。<style> 里的 CSS 变成一个 JavaScript 字符串,其中的花括号不再被当作 JSX;里面的实体会被解码,<![CDATA[ ... ]]> 外壳会被去掉。style 属性变成对象,值按原文复制;xlink:href 变成 xlinkHref。用 esbuild 0.21.5 编译、React 19.2.0 开发版渲染,结果是 <svg viewBox="0 0 24 24"><defs><style>.cls-1{fill:#e11d48;}</style></defs><path id="a" class="cls-1" style="stroke:#000;stroke-width:2" d="M12 5v14"></path><use xlink:href="#a"></use></svg>,控制台没有警告。
粘贴前:导出设置
- Figma:选中图层 → Export → SVG。除非要按 ID 操作元素,否则不勾「Include “id” attribute」。
- Illustrator:File → Export → Export As → SVG(菜单名按英文界面)。Styling 选 Presentation Attributes 得到的组件最短。Internal CSS、Inline Style 会生成
<style>块或style="..."字符串(Adobe:SVG 导出选项),本工具会把它们转成 CSS 字符串和样式对象,见上例。<style>块对整个页面生效,两个图标都用.cls-1时会互相改颜色。 - 工具会去掉
<?xml ... ?>声明,并把注释转成 JSX 注释,<!-- Generator: ... -->不必先删。
仍需手动修改的地方
下表每一行都用 esbuild 0.21.5 编译输出、再用 React 19.2.0 渲染核对过。
| 粘贴的 SVG 里 | 工具输出 | 在 React 中的结果 | 改成 |
|---|---|---|---|
style="fill:red !important"、同一属性写两次、style 里有 CSS 注释 | 无输出:拒绝转换、停用复制,状态栏给出样式中的位置 | — | 把规则移到 <style> 块或 CSS 文件里,或去掉 !important |
<text>{count}</text> | <text>{count}</text> | 显示文字 {count} | 想用变量就自己改成 {count} |
写死的 fill / stroke 颜色 | 原样保留 | 图标不跟随文字颜色 | fill="currentColor" / stroke="currentColor" |
<style> 里的类名和其他图标重复 | CSS 字符串 | 规则对整个页面生效 | 改类名,或用 Presentation Attributes 导出 |
限制
- 用正则匹配,不是 XML 解析器:先识别注释、
<style>块和 CDATA,所以写在<!-- ... -->里的标签不会被转换。带引号的属性值里可以有>和/。不会补全未闭合的标签。 - 值按原文复制:只改属性名,
aria-label="class schedule"仍是aria-label="class schedule"。例外是style(变成对象)和文字:文字里的{、}、<、>写成{、}、<、>,React 显示的仍是原字符。 - React 对象无法保留的样式会被拒绝:
style属性里有!important、同一属性写两次(CSS 回退)、CSS 注释、含转义的属性名、未闭合的引号或括号时停止转换,清空输出并停用复制,直到输入改变。 - 一次一个组件:只有第一个
<svg>会加{...props},雪碧图请逐个图标粘贴。 - 组件名:字母、数字、
_、$以外的字符会被删掉,首字母自动大写(plus-icon→Plusicon)。中文组件名会被整段删掉,回退为MyIcon。 data-*与aria-*属性保留连字符,这也是 React 的要求。
FAQ
SVG 转 JSX 工具做什么?
它将原始 SVG 文件转换为可复用的 React 组件。主要变更包括:将连字符属性转为驼峰命名(stroke-width → strokeWidth)、将 class 重命名为 className、移除 xmlns 声明,并将 SVG 标记包裹在函数组件中。
为什么要重命名 SVG 属性?
JSX 会被编译为 JavaScript,连字符属性名不是合法的 JS 标识符。React 要求使用驼峰命名版本,如 strokeWidth、fillRule、clipPath 等。
TypeScript 选项有什么作用?
启用后,输出使用 React.FC<React.SVGProps<SVGSVGElement>> 作为组件类型,提供完整的 TypeScript 支持,包括 SVG 属性的自动补全。
forwardRef 有什么用?
forwardRef 允许父组件将 ref 附加到底层 SVG 元素,适用于需要以编程方式访问 DOM 节点的场景,例如测量尺寸或触发动画。
memo 包裹有什么作用?
React.memo 包裹组件,使其仅在 props 变化时才重新渲染,是图标组件的性能优化手段。
数据会发送到服务器吗?
不会。转换在浏览器中通过 JavaScript 运行,不传输任何 SVG 数据。