人称外号大脸猫

Vite 项目中 SVG 图标组件化最佳实践

通过 vite-plugin-svg-icons 实现 SVG 图标的自动化管理、全局组件集成和动态样式控制,提升开发效率和项目可维护性。

📦 安装依赖

npm install vite-plugin-svg-icons -D

⚙️ Vite 配置 (vite.config.js)

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'

export default defineConfig({
  plugins: [
    vue(),
    createSvgIconsPlugin({
      // 指定 SVG 图标存放目录
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      
      // 定义 symbolId 生成规则
      symbolId: 'icon-[dir]-[name]'
    })
  ]
})

🧩 全局组件实现 (src/components/SvgIcon.vue)

<template>
   <svg
           aria-hidden="true"
           class="svg-icon"
           :class="className"
           :style="{ color, fontSize: size }"
   >
      <use :xlink:href="symbolId" />
   </svg>
</template>

<script setup>
   import { computed } from 'vue'

   const props = defineProps({
      name: { type: String, required: true },
      prefix: { type: String, default: 'icon' },
      className: { type: String, default: '' },
      color: { type: String },  // 颜色控制属性
      size: { type: String }    // 尺寸控制属性
   })

   const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>

<style scoped>
   .svg-icon {
      display: inline-block;
      width: 1em;
      height: 1em;
      vertical-align: -0.15em;
      fill: currentColor;  /* 继承父级颜色 */
      overflow: hidden;
   }
</style>

🌐 全局注册 (main.js)

import 'virtual:svg-icons-register'  // 激活 SVG 自动化注册
import SvgIcon from '@/components/SvgIcon.vue'

app.component('SvgIcon', SvgIcon)  // 全局注册组件

🚀 使用示例

<!-- 基础用法 -->
<SvgIcon name="search" />

<!-- 进阶用法 -->
<SvgIcon
        name="user-profile"
        class="icon-highlight"
        color="#42b983"
        size="24px"
/>
import 'virtual:svg-icons-register'
3. 安装依赖
```shell
  npm i vite-plugin-svg-icons -D
  1. 配置vite.config.js
import {createSvgIconsPlugin} from 'vite-plugin-svg-icons'
import path from 'path'
export default defineConfig({
  plugins: [
    vue(),
    createSvgIconsPlugin({
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      symbolId: 'icon-[dir]-[name]',
    }),
  ],
})
  1. 创建全局组件 (src/components/SvgIcon.vue)
<template>
  <svg aria-hidden="true" class="svg-icon" :class="className">
    <use :xlink:href="symbolId" />
  </svg>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  prefix: {
    type: String,
    default: 'icon'
  },
  name: {
    type: String,
    required: true
  },
  className: {
    type: String,
    default: ''
  }
})

const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>
  1. 在main.js中全局注册组件
import 'virtual:svg-icons-register'
import SvgIcon from './components/SvgIcon.vue'
app.component('SvgIcon', SvgIcon)
  1. 在页面中使用
<SvgIcon name="search" />

✨ 优化亮点

  1. 动态样式控制
  • 新增 color 和 size 属性实现动态样式调整
  • 保留 className 支持自定义类名
  1. 语义化改进
  • 更清晰的属性命名(name → 图标名称)
  • 移除冗余的 prefix 默认值声明
  1. 样式增强
  • 添加 display: inline-block 避免布局偏移
  • 使用 currentColor 实现颜色继承
  1. 错误预防
  • 强化 name 属性的必填校验
  • 明确注释关键配置的作用

💡 最佳实践建议

  1. 图标存放路径 src/assets/icons/(支持多级目录结构)

  2. 命名规范

  • 文件命名:search.svg → 使用名:name="search"
  • 子目录文件:user/profile.svg → 使用名:name="user-profile"
  1. 尺寸单位 优先使用 em 单位保持与文本的比例关系

  2. 颜色控制 通过父级 CSS 的 color 属性或组件的 color prop 控制

copyright ©2025 ahimu.com all rights reserved 皖ICP备19021547号-1