我当时首先想到的是 搬运vue2 中svg的使用方式,安装svg-sprite-loader 和做相应的封装。(vue2+ svg)你会发现 行不通,因为本项目使用的是vite 构建的无法使用Webpack所以如下代码不执行的
// 自动化加载
// webpack的require.context方法自动化加载
const req = require.context('./svg', false, /\.svg$/)
// req.keys() 拿到上下文中所有的文件名称
req.keys().map(req)
翻阅vite 文档你会发现:Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块,默认这个方法是异步的,我们需要加上第二个参数{ eager: true }同步获取.
语法:
const modules = import.meta.glob('./dir/*.vue', { eager: true })
我的使用方式
<script setup lang="ts">
import { shallowRef, defineAsyncComponent, type Component, computed, withDefaults } from 'vue'
interface Props {
iconName: string,
viewBox: string
}
const props = withDefaults(defineProps<Props>(), {
iconName: '',
viewBox: ''
})
// 动态获取异步组件集合
const modules = import.meta.glob('./svg/*.vue')
// 声明一个对象承载异步加载来的组件
// let comObj:Record<string, object> = {}
// for (const path in modules) {
// // 获取组件文件的名称,这里以vue文件名称作为对象的key
// const key:string = path.replace(/(.*\/)*([^.]+).vue/ig, "$2")
// if (key === props.iconName) {
// comObj[key] = defineAsyncComponent(() =>
// import(path)
// )
// }
// }
let Comp: Component = null
const item:Array<string, () => Component> = Object.entries(modules).find(item => item[0].includes(props.iconName))
if (item) {
Comp = defineAsyncComponent(item[1])
}
// 所有动态加载的异步组件集合
const comp = shallowRef<Component>(Comp)
</script>
<template>
<component :is="comp" class="svg-icon" :viewBox="viewBox" />
</template>
<style lang="scss" scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
// 先引入
import SvgIcon from '@/components/icons/index.vue'
// 使用
<span class="svg-container">
<svg-icon icon-name="IconUser" viewBox="0 0 120 120" width="100" height="100" />
</span>
上述代码有个细节点 注意,那就是 viewBox width height 属性 用于控制svg 展示的大小的;