目录
需求
在vue3项目中,需要批量导入某个文件夹内数量不确定的svg文件用来作为图标,开发完成后能够通过增减文件夹内的svg文件,从而影响图标的数量。
svg使用简述
svg是一种 xml语言,svg作为html标签使用的时候,除了svg标签<svg> <path d="*"/> </svg>
和<img src="svg_url">
外,还有很多方式可以使用。
本次仅使用其中的symbol
属性,更多详情参阅相关文档 MDN-svg
<symbol>
元素用来在document中生成图形模板,提供给<use>
元素实例化显示。
<symbol>
元素本身是隐藏的,实例化后的元素才会显示<symbol>
元素仅需插入一次,可多次通过<use>
复用- < use xlink:href="#symId" >标签属性
xlink:href
与< symbol id="symId" >标签属性id
相对应
插件使用简述
vite-plugin-svg-icons
是一个vite插件,提供轻松导入svg文件作为symbol元素并插入到document中的功能。
使用起来也十分容易,只需要在vite.config.ts
中加个配置,然后在src/main.ts
中引入即可
详情参阅 插件中文文档
实现
原本我想使用vite提供的批量导入文件来实现
import.meta.glob('/src/**/*.svg')
不过这种方式需要写一大堆异步方法去解决文件动态导入的问题,而且用户体验并不好,还引发了vue3报issue
所以最终选择使用插件在编译的时候就导入所有svg文件,解决了动态导入的问题,让业务逻辑更流畅
安装插件
c
npm i vite-plugin-svg-icons -D
1、配置vite.config.ts
javascript
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default () => {
return {
plugins: [
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), 'src/assets/icon-svg/')],
// 指定symbolId格式
symbolId: 'icon-svg-[name]',
}),
}),
],
}
}
2、src/main.ts引入注册脚本
javascript
import 'virtual:svg-icons-register'
到这里svg 雪碧图就已经生成到页面的body中了
3、写个icon组件
接收一个name
参数,对应symbol
的id
属性
html
<template>
<svg aria-hidden="true" >
<use :xlink:href="symbolId" />
</svg>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Props {
name: string;
}
const props = defineProps<Props>();
const symbolId = computed(() => `#icon-svg-${props.name}`);
</script>
4、使用组件
在页面里使用组件
html
<template>
<el-icon :size="32">
<!-- name值和文件名对应 -->
<SvgIcon name="404" />
</el-icon>
</template>
<script setup lang="ts">
// 导入组件
import SvgIcon from '@/components/SvgIcon.vue';
</script>
图标出来了
如果需要批量导入
html
<template>
<template v-for="(e, i) in svgList" :key="i">
<el-icon :size="32">
<component :is="e.module" :name="e.name"></component>
</el-icon>
</template>
</template>
<script setup lang="ts">
import SvgIcon from '@/components/SvgIcon.vue';
// 引入/src/assets/icon-svg/文件夹下的所有svg文件
const svgModules = import.meta.glob('/src/assets/icon-svg/*.svg');
const svgList = Object.keys(svgModules).map((key) => ({
name: key.replace(/^.*\/(\S+)\..*/, '$1'),
module: SvgIcon,
}));
</script>
然后图标就有了