详细讲一下在 Vite 项目中如何使用 SVG 图标(干货满满)

1. 基础设置

首先需要安装必要的依赖

# 安装 vite-plugin-svg-icons
npm install vite-plugin-svg-icons -D

# 如果需要使用 svg 组件
npm install @vicons/ionicons5 -D

2. Vite 配置

// vite.config.js
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'

export default defineConfig({
  plugins: [
    createSvgIconsPlugin({
      // 指定 SVG 图标目录
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      // 指定symbolId格式
      symbolId: 'icon-[dir]-[name]'
    })
  ]
})

3. 主文件引入

// main.js
import 'virtual:svg-icons-register'

4. 创建 SvgIcon 组件   

<!-- src/components/SvgIcon.vue -->
<template>
  <svg aria-hidden="true" class="svg-icon">
    <use :href="symbolId" :fill="color"/>
  </svg>
</template>

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

const props = defineProps({
  // 图标名称
  name: {
    type: String,
    required: true
  },
  // 图标颜色
  color: {
    type: String,
    default: '#333'
  },
  // 图标大小
  size: {
    type: [Number, String],
    default: 16
  }
})

// 计算图标的symbolId
const symbolId = computed(() => `#icon-${props.name}`)
</script>

<style scoped>
.svg-icon {
  width: v-bind('`${props.size}px`');
  height: v-bind('`${props.size}px`');
  vertical-align: middle;
  fill: currentColor;
  overflow: hidden;
}
</style>

     

5. 全局注册组件

// src/components/index.js
import SvgIcon from './SvgIcon.vue'

export default {
  install(app) {
    app.component('SvgIcon', SvgIcon)
  }
}

// main.js
import Components from './components'
app.use(Components)

6. 使用方式

<template>
  <!-- 基本使用 -->
  <svg-icon name="user" />
  
  <!-- 设置颜色和大小 -->
  <svg-icon 
    name="user" 
    color="#ff0000"
    :size="24"
  />
</template>

7. 进阶用法

1. 创建图标管理器

// src/utils/iconManager.js
export const iconList = {
  user: 'user',
  home: 'home',
  settings: 'settings'
  // ... 更多图标
}

export const getIconName = (name) => {
  return iconList[name] || name
}

2.封装通用组件:

<!-- src/components/Icon/index.vue -->
<template>
  <div class="icon-wrapper" :class="wrapperClass">
    <svg-icon
      :name="iconName"
      :size="size"
      :color="color"
      @click="handleClick"
    />
    <slot></slot>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { getIconName } from '@/utils/iconManager'

const props = defineProps({
  name: String,
  size: {
    type: [Number, String],
    default: 16
  },
  color: String,
  disabled: Boolean,
  clickable: Boolean
})

const emit = defineEmits(['click'])

const iconName = computed(() => getIconName(props.name))

const wrapperClass = computed(() => ({
  'is-disabled': props.disabled,
  'is-clickable': props.clickable
}))

const handleClick = (e) => {
  if (props.disabled) return
  emit('click', e)
}
</script>

<style scoped>
.icon-wrapper {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.is-clickable {
  cursor: pointer;
}

.is-disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
</style>

8. 实际应用示例

1.导航菜单:

<template>
  <div class="menu">
    <div 
      v-for="item in menuItems" 
      :key="item.id"
      class="menu-item"
    >
      <svg-icon 
        :name="item.icon"
        :size="20"
        :color="item.active ? '#1890ff' : '#666'"
      />
      <span>{{ item.title }}</span>
    </div>
  </div>
</template>

<script setup>
const menuItems = [
  { id: 1, title: '首页', icon: 'home', active: true },
  { id: 2, title: '用户', icon: 'user', active: false },
  { id: 3, title: '设置', icon: 'settings', active: false }
]
</script>

2.按钮组件:

<template>
  <button 
    class="icon-button"
    :class="{ 'is-loading': loading }"
  >
    <svg-icon 
      v-if="loading"
      name="loading"
      class="loading-icon"
    />
    <svg-icon 
      :name="icon"
      :size="16"
    />
    <span><slot></slot></span>
  </button>
</template>

<style scoped>
.icon-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.loading-icon {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
</style>

9.最佳实践

1.组织SVG文件

src/
  assets/
    icons/
      common/     # 通用图标
        home.svg
        user.svg
      business/   # 业务图标
        product.svg
        order.svg

2.图标命名规范:

// 推荐的命名方式
icon-[模块]-[名称]-[状态]

// 例如
icon-common-home
icon-business-product-active

3.按需加载:

// vite.config.js
createSvgIconsPlugin({
  iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
  symbolId: 'icon-[dir]-[name]',
  inject: 'body-last',
  customDomId: '__svg__icons__dom__'
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值