You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue组合式API中使用<component :is>加载SVG的实现问题

解决Vue组合式API中通过<component :is>动态加载SVG的问题

你的代码核心问题在于:动态import SVG文件返回的是模块对象,而非可直接用于<component :is>的Vue组件。同时当前useSvgLoader的import路径混用了@和~/别名,需要统一。以下是具体修复方案:

1. 调整SVG导入逻辑(适配打包工具)

根据你使用的打包工具,确保SVG能被编译为Vue组件:

  • Vite:在import路径后添加?component后缀,Vite会自动将SVG转为Vue单文件组件
  • Webpack:需配置svg-vue-loader等loader,确保SVG被解析为组件

修改useSvgLoader组合式函数:

export enum IconPack {
    Utility,
    Action,
    Custom,
    Doctype,
    Standard
}

export function useSvgLoader(iconName: string, iconPack: IconPack = IconPack.Utility ){
    const name = `${iconName}.svg`
    // 统一使用@作为src目录别名,需确保项目已配置该别名
    switch (iconPack) {
        case IconPack.Utility: return import(`@/assets/icons/utility/${name}?component`)
        case IconPack.Action: return import(`@/assets/icons/action/${name}?component`)
        case IconPack.Custom: return import(`@/assets/icons/custom/${name}?component`)
        case IconPack.Doctype: return import(`@/assets/icons/doctype/${name}?component`)
        case IconPack.Standard: return import(`@/assets/icons/standard/${name}?component`)
    }
}

2. 修正组件获取逻辑

asyncComputed中需要提取模块的default导出(Vue组件默认挂载在模块的default属性上),同时添加错误处理:

修改LoadSvg.vue:

<template>
  <!-- 增加加载状态与错误占位 -->
  <div v-if="svgData.loading">加载中...</div>
  <div v-else-if="svgData.error">图标加载失败</div>
  <component v-else :is="svgData.value" />
</template>
<script setup lang="ts">
import { IconPack, useSvgLoader } from "@/composables/useSvgLoader";
import { asyncComputed } from "@vueuse/core";

const props = withDefaults(
  defineProps<{
    name: string
    pack: IconPack
  }>(), {
    name: "add",
    pack: IconPack.Utility
  }
)

const svgData = asyncComputed(async () => {
  try {
    // 提取模块中的Vue组件
    const svgModule = await useSvgLoader(props.name, props.pack);
    return svgModule.default;
  } catch (err) {
    console.error(`加载图标${props.name}失败:`, err);
    throw err;
  }
})
</script>

3. 备选方案:直接渲染SVG字符串

如果不需要将SVG转为Vue组件,也可以加载原始SVG字符串并通过v-html渲染:

<template>
  <div v-html="svgData.value"></div>
</template>
<script setup lang="ts">
// 修改useSvgLoader的import后缀为?raw(Vite)
// export function useSvgLoader(...) { return import(`xxx.svg?raw`) }
const svgData = asyncComputed(async () => {
  const module = await useSvgLoader(props.name, props.pack);
  return module.default;
})
</script>

内容的提问来源于stack exchange,提问作者Kid A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:43:20