跳到正文
SvgJsx
语言: 中文

把 SVG 转换为 Vue 单文件组件

把任意 SVG 包装成 Vue 3 单文件组件(.vue):干净的 <template>、可选的 <script setup lang="ts"> 和 size 属性,直接导入即可使用。

快速预设:
将 .svg 文件拖放到这里,或文件通过 FileReader 在本地读取,绝不会上传。
选项
导出方式:
<script setup lang="ts">
defineOptions({ name: "HeartIcon" });
</script>

<template>
  <svg width="24" height="24" viewBox="0 0 24 24" class="icon icon-heart">
    <g id="Layer_1" fill="none" stroke="#e11d48" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <path d="M19.0001 14.0002c1.4900-1.4600 3.0000-3.2100 3.0000-5.5000A5.5000 5.5000 0 0 0 16.5000 3c-1.7600 0-3.0000.5000-4.5000 2-1.5000-1.5000-2.7400-2-4.5000-2A5.5000 5.5000 0 0 0 2 8.5000c0 2.3000 1.5000 4.0500 3 5.5000l7 7Z" style="fill-opacity:0.15;fill:#e11d48" />
    </g>
  </svg>
</template>

预览

转换后 SVG 的预览
原始 SVG
706 B
优化后 SVG
538 B(-24%)
组件
580 B

Vue 输出是什么样的

Vue 模板可以原样接受 SVG 属性,所以转换器会保留 stroke-width、class 等短横线写法。它会清除编辑器残留信息和 XML 声明,并可选择移除 xmlns,然后把标记放进 <template> 块中。

开启 size 选项后,会生成一个 <script setup> 块,声明带默认值的 size 属性,并绑定到 :width 和 :height。使用 TypeScript 时,属性通过 defineProps<{ size?: number | string }>() 和 withDefaults 声明。

属性透传

由于 <svg> 是唯一的根元素,Vue 会自动把未声明为 props 的属性透传给它。也就是说,class、style、aria-label 以及 @click 等事件监听器都会直接作用在 <svg> 上,不需要额外代码。因此 Vue 不需要 props 展开选项。

使用组件

在 Vue 3 或 Nuxt 项目中的典型用法:

  • 把输出保存为 components 目录中的 IconName.vue。
  • 导入它:import IconName from "./IconName.vue"。
  • 在任意模板中渲染 <IconName :size="20" class="text-emerald-600" />。
  • 开启 currentColor 后,图标颜色会跟随 CSS 的 color 属性。

常见问题

输出的代码能用于 Vue 2 吗?

模板部分在 Vue 2.7 中也能使用,但带 defineProps 的 <script setup> 需要 Vue 2.7 或 Vue 3。更早的 Vue 2 项目请关闭 size 属性,生成只含模板的组件。

可以在 Nuxt 中使用吗?

可以。把文件放进 components 目录,Nuxt 会按名称自动导入,例如 components/IconArrow.vue 对应 <IconArrow />。

为什么 Vue 会对 SVG 里的 <style> 发出警告?

<style> 标签有副作用,所以 Vue 会把它们从模板中移除。请把 CSS 移到组件的 <style scoped> 块中,或在转换前把它改写为属性。

vite-svg-loader 是不是更好的选择?

如果需要在构建时导入大量 SVG,loader 会更方便。转换成 .vue 文件则让你完全掌控标记和 props,而且无需任何构建配置。