vue3+ts系列之svg图标封装(生成雪碧图/精灵图)

574 阅读1分钟
  • 当svg图标过多时,每次都会单独请求,影响性能,打包成雪碧图后,仅请求一次
  • 预加载 在项目运行时就生成所有图标,只需操作一次 dom
  • 高性能 内置缓存,仅当文件被修改时才会重新生成

一、安装依赖

yarn add vite-plugin-svg-icons -D
# or
npm i vite-plugin-svg-icons -D
# or
pnpm install vite-plugin-svg-icons -D

二、vite.config.ts配置

// vite.config.ts

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

export default () => {
  return {
    plugins: [
      createSvgIconsPlugin({
        // 指定需要缓存的图标文件夹
        iconDirs: [path.resolve(process.cwd(), 'src/icons')],
        // 指定symbolId格式
        symbolId: 'icon-[dir]-[name]',

        /**
         * 自定义插入位置
         * @default: body-last
         */
        inject?: 'body-last' | 'body-first'

        /**
         * custom dom id
         * @default: __svg__icons__dom__
         */
        customDomId: '__svg__icons__dom__',
      }),
    ],
  }
}

三、引入插件生成的雪碧图/精灵图

// main.ts

import 'virtual:svg-icons-register'

四、封装svg组件

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

<script setup lang="ts">
import { computed } from 'vue'

const props = withDefaults(
  defineProps<{
    prefix: string
    name: string // svg图标的格式: 路径(icons目录下具体的路径,若没有放在里面的文件夹,则没有这一项)-名称
    color?: string // 填充颜色
    className: string // 自定义类名
  }>(),
  {
    prefix: 'icon',
    className: 'default_class'
  }
)

const symbolId = computed(() => {
  return `#${props.prefix}-${props.name}`
})
</script>
<style scoped lang="scss">
.default_class {
  width: 1em;
  height: 1em;
}
</style>

五、新增icons目录

# src/icons

- icon1.svg
- icon2.svg
- icon3.svg
- dir/icon1.svg

六、在vue组件中使用

<template>
  <div>
    <SvgIcon name="icon1"></SvgIcon>
    <SvgIcon name="icon2"></SvgIcon>
    <SvgIcon name="icon3"></SvgIcon>
     <!-- svg图标在dir文件下 -->
    <SvgIcon name="dir-icon1"></SvgIcon>
  </div>
</template>

<script>
import { defineComponent, computed } from 'vue'

import SvgIcon from './components/SvgIcon.vue'
export default defineComponent({
  name: 'App',
  components: { SvgIcon },
})
</script>

参考:github.com/vbenjs/vite…