vue3 vite 使用svg图

文章介绍了在Vue项目中如何安装和使用svg-sprite-loader来处理SVG图标,包括创建SVG组件、在assets文件夹下组织SVG图标,以及通过自定义Vite插件自动化处理SVG并全局注册组件。此外,还提供了从阿里巴巴图库获取SVG图标的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 安装svg-sprite-loader

npm install svg-sprite-loader -D

  1. 在components文件下创建svg文件,编写全局svg组件

<template>
  <svg :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>
<script setup lang="ts">
const props = defineProps({
  iconClass: {
    type: String,
    required: true,
  },
  className: {
    type: String,
    default: '',
  },
})

const svgClass = computed(() => {
  if (props.className) {
    return 'svg-icon ' + props.className
  } else {
    return 'svg-icon'
  }
})
const iconName = computed(() => {
  return `#icon-${props.iconClass}`
})
</script>
<style lang="less">
.svg-icon {
  width: 1em;
  height: 1em;
  fill: currentColor;
  vertical-align: middle;
}
</style>
  1. 在assets文件夹下创建icon,放入svg图片

  1. main入口文件注册全局组件svg

import { createApp } from 'vue'
import App from './App.vue'

import svgIcon from './components/svgIcon.vue'

createApp(App).component('svg-icon', svgIcon).mount('#app');
  1. 手写config插件(重点)

// js

import { readFileSync, readdirSync } from 'fs'

let idPerfix = ''
const svgTitle = /<svg([^>+].*?)>/
const clearHeightWidth = /(width|height)="([^>+].*?)"/g

const hasViewBox = /(viewBox="[^>+].*?")/g

const clearReturn = /(\r)|(\n)/g

function findSvgFile(dir) {
  const svgRes = []
  const dirents = readdirSync(dir, {
    withFileTypes: true,
  })
  for (const dirent of dirents) {
    if (dirent.isDirectory()) {
      svgRes.push(...findSvgFile(dir + dirent.name + '/'))
    } else {
      const svg = readFileSync(dir + dirent.name)
        .toString()
        .replace(clearReturn, '')
        .replace(svgTitle, ($1, $2) => {
          // console.log(++i)
          // console.log(dirent.name)
          let width = 0
          let height = 0
          let content = $2.replace(clearHeightWidth, (s1, s2, s3) => {
            if (s2 === 'width') {
              width = s3
            } else if (s2 === 'height') {
              height = s3
            }
            return ''
          })
          if (!hasViewBox.test($2)) {
            content += `viewBox="0 0 ${width} ${height}"`
          }
          return `<symbol id="${idPerfix}-${dirent.name.replace(
            '.svg',
            ''
          )}" ${content}>`
        })
        .replace('</svg>', '</symbol>')
      svgRes.push(svg)
    }
  }
  return svgRes
}

export const svgBuilder = (path, perfix = 'icon') => {
  if (path === '') return
  idPerfix = perfix
  const res = findSvgFile(path)
  // console.log(res.length)
  // const res = []
  return {
    name: 'svg-transform',
    transformIndexHtml(html) {
      return html.replace(
        '<body>',
        `
          <body>
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
              ${res.join('')}
            </svg>
        `
      )
    },
  }
}

// ts

import { Plugin } from 'vite'
import { readFileSync, readdirSync } from 'fs'

let idPerfix = ''
const svgTitle = /<svg([^>+].*?)>/
const clearHeightWidth = /(width|height)="([^>+].*?)"/g

const hasViewBox = /(viewBox="[^>+].*?")/g

const clearReturn = /(\r)|(\n)/g

function findSvgFile(dir): string[] {
  const svgRes = []
  const dirents = readdirSync(dir, {
    withFileTypes: true
  })
  for (const dirent of dirents) {
    if (dirent.isDirectory()) {
      svgRes.push(...findSvgFile(dir + dirent.name + '/'))
    } else {
      const svg = readFileSync(dir + dirent.name)
        .toString()
        .replace(clearReturn, '')
        .replace(svgTitle, ($1, $2) => {
          // console.log(++i)
          // console.log(dirent.name)
          let width = 0
          let height = 0
          let content = $2.replace(
            clearHeightWidth,
            (s1, s2, s3) => {
              if (s2 === 'width') {
                width = s3
              } else if (s2 === 'height') {
                height = s3
              }
              return ''
            }
          )
          if (!hasViewBox.test($2)) {
            content += `viewBox="0 0 ${width} ${height}"`
          }
          return `<symbol id="${idPerfix}-${dirent.name.replace(
            '.svg',
            ''
          )}" ${content}>`
        })
        .replace('</svg>', '</symbol>')
      svgRes.push(svg)
    }
  }
  return svgRes
}

export const svgBuilder = (
  path: string,
  perfix = 'icon'
): Plugin => {
  if (path === '') return
  idPerfix = perfix
  const res = findSvgFile(path)
  // console.log(res.length)
  // const res = []
  return {
    name: 'svg-transform',
    transformIndexHtml(html): string {
      return html.replace(
        '<body>',
        `
          <body>
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
              ${res.join('')}
            </svg>
        `
      )
    }
  }
}
  1. vite.config.文件中引入插件

import { svgBuilder } from './src/plugins/svgBuilder.js' 

export default defineConfig({
  plugins: [
    ...
    // 这里已经将src/icons/svg/下的svg全部导入,无需再单独导入
    svgBuilder('./src/assets/icons/svg/') 
  ] 

})

vue中引入:

<svg-icon class-name="add" icon-class="add" />

用法:icon-class 直接写svg图片名,然后想加样式的话,直接用class-name在vue文件中写样式即可。

附:svg图片获取方式

从阿里巴巴图库中找到自己想要的图标,点击下载,复制svg代码或者下载svg图片放入对一个文件夹即可。

https://www.iconfont.cn/

### 使用 Vite 和 `svg-sprite-loader` 处理 Vue 3 中的 SVG 标 对于在 Vue 3 项目中使用 Vite 构建工具并结合 `svg-sprite-loader` 来处理 SVG 标的场景,可以按照如下方式实现。 #### 安装依赖包 安装必要的插件以支持 SVG 标作为雪碧加载: ```bash npm install vite-plugin-svg-icons -D ``` #### 配置 Vite 插件 编辑项目的 `vite.config.js` 文件,在 plugins 数组内加入创建好的配置对象: ```javascript import { defineConfig } from &#39;vite&#39;; import vue from &#39;@vitejs/plugin-vue&#39;; import path from &#39;path&#39;; import { createSvgIconsPlugin } from &#39;vite-plugin-svg-icons&#39;; export default defineConfig({ plugins: [ vue(), createSvgIconsPlugin({ iconDirs: [path.resolve(process.cwd(), &#39;src/components/svgIcon/svg&#39;)], symbolId: &#39;icon-[name]&#39;, inject: &#39;body-last&#39;, customDomId: &#39;__svg__icons__dom__&#39; }) ] }); ``` 上述设置指定了标所在的文件夹路径以及如何生成 `<symbol>` 的 ID 属性[^3]。 #### 创建和使用 SVG 组件 为了方便复用这些标,建议封装一个通用的 SVG Icon 组件。该组件可以根据传入的名字动态渲染对应的标实例。 ```html <template> <svg class="svg-icon" aria-hidden="true"> <use :xlink:href="&#39;#&#39; + iconName"></use> </svg> </template> <script setup lang="ts"> defineProps<{ iconName: string; }>(); </script> <style scoped> .svg-icon { width: 1em; height: 1em; } </style> ``` 此模板中的 `iconName` 是父级传递给子组件的一个属性,用于指定要显示的具体标名称[^2]。 当需要展示某个特定的标时,只需简单调用这个自定义组件即可: ```vue <MySvgIcon :icon-name="&#39;example&#39;" /> ``` 这样就完成了基于 Vite 和 `svg-sprite-loader` 对于 Vue 3 应用程序中 SVG 标的高效管理与应用[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值