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
相关产品推荐
相关产品推荐

