在 Vue3 项目中,将 SVG 图标集中管理并方便地在各个组件中使用,是一个非常常见的需求。结合“可变色”和“公共管理”这两个核心点,以下是几种最佳实践方案:
方案一:SVG 组件化 + 自动导入
这是目前最流行、最灵活、最易维护的方式。将每个 SVG 文件转换为一个独立的 Vue 组件,并通过工具自动注册。
目录结构
src/
├── components/
│ └── SvgIcon.vue # 通用 SVG 图标组件
├── assets/
│ └── icons/ # 所有 SVG 文件集中存放
│ ├── user.svg
│ ├── home.svg
│ ├── setting.svg
│ └── ...
└── plugins/
└── svgIcon.js # SVG 组件自动导入脚本
创建通用 SVG 组件 SvgIcon.vue
<!-- components/SvgIcon.vue -->
<template>
<svg
:class="['svg-icon', className]"
:style="{ width: size, height: size, color: color }"
aria-hidden="true"
<use :href="symbolId" :fill="color" />
</svg>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
// 图标名称,如 'user'
name: {
type: String,
required: true
},
// 图标大小
size: {
type: String,
default: '1em'
},
// 图标颜色(支持 CSS 颜色值)
color: {
type: String,
default: 'currentColor'
},
// 自定义 class
className: {
type: String,
default: ''
}
})
// 生成 symbol 的 ID,格式为 #icon-name
const symbolId = computed(() => #icon-${props.name})
</script>
<style scoped>
.svg-icon {
display: inline-block;
vertical-align: -0.15em;
fill: currentColor; / 关键:让 fill 继承 color /
overflow: hidden;
}
</style>
自动导入 SVG 文件并注册为 symbol
// plugins/svgIcon.js
import { createApp } from 'vue'
// 使用 import.meta.glob 动态导入 assets/icons/ 下的所有 .svg 文件
const svgModules = import.meta.glob('@/assets/icons/*.svg', { as: 'raw', eager: false })
// 在应用启动时执行
export function setupSvg(app) {
const div = document.createElement('div')
div.style.display = 'none'
let svgStr = '<svg xmlns="http://www.w3.org/2000/svg">'
// 遍历所有 SVG 文件
Object.keys(svgModules).forEach(async (path) => {
const response = await svgModules[path]()
// 提取文件名作为 icon name
const name = path.match(/\/([^/]+)\.svg$/)[1]
// 将 SVG 内容包装成 <symbol>
const symbol = response
.replace('<svg', <symbol id="icon-${name}")
.replace('</svg>', '</symbol>')
svgStr += symbol
})
svgStr += '</svg>'
div.innerHTML = svgStr
document.body.insertBefore(div, document.body.firstChild)
}
在 main.js 中注册
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { setupSvg } from './plugins/svgIcon'
const app = createApp(App)
// 注册 SVG 图标
setupSvg(app)
app.mount('#app')
5. 在任意组件中使用
vue
<template>
<div>
<!-- 使用 -->
<SvgIcon name="user" size="24px" color="red" />
<SvgIcon name="home" color="blue" />
<SvgIcon name="setting" style="color: green;" />
</div>
</template>
<script setup>
// 只需引入一次组件即可
import SvgIcon from '@/components/SvgIcon.vue'
</script>
优点:
- 集中管理所有 SVG 文件
- 支持动态变色(通过 color 属性)
- 支持按需加载(import.meta.glob)
- 使用简单,像使用普通组件一样 构建时自动处理,无需手动维护
方案二:使用第三方库(如 vite-plugin-svg-icons)
如果你使用 Vite,可以使用现成的插件,更加省事。
安装
npm install vite-plugin-svg-icons -D
配置 vite.config.js
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default {
plugins: [
createSvgIconsPlugin({
// 指定 SVG 文件夹
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// 指定 symbolId 格式
symbolId: 'icon-[name]'
})
]
}
在 main.js 中引入生成的脚本
// main.js
import 'virtual:svg-icons-register' // 插件会生成这个虚拟模块
使用方式同方案一的 SvgIcon.vue 组件
只需创建一个通用的 SvgIcon.vue 组件,然后在项目中使用即可。
不推荐的方式
<img src="xxx.svg">:无法通过 CSS 改变颜色。CSS background-image:同样无法控制内部颜色,且不利于响应式。- 手动维护所有 SVG 内容:维护成本高,不推荐。
总结
- 组件化 + 自动导入 强烈推荐 纯手动实现,灵活可控
- vite-plugin-svg-icons 推荐 使用 Vite 插件,更简单
- 内联 SVG 代码 一般 适合图标少的项目
- img或 background 不推荐 无法变色
选择 方案一 或 方案二,将 SVG 集中管理,通过 SvgIcon 组件统一调用,既能实现变色,又能方便维护。
940

被折叠的 条评论
为什么被折叠?



