https://github.com/vbenjs/vite-plugin-svg-icons/
创建一个空的 vue 项目
pnpm create vue
┌ Vue.js - The Progressive JavaScript Framework
◇ 请输入项目名称:
│ vueSvg
│
◇ 请输入包名称:
│ vuesvg
│
◇ 请选择要包含的功能: (↑/↓ 切换,空格选择,a 全选,回车确认)
│ TypeScript, ESLint(错误预防), Prettier(代码格式化)
│
◇ 选择要包含的试验特性: (↑/↓ 切换,空格选择,a 全选,回车确认)
│ none
│
正在初始化项目 C:\Users\Windows\Desktop\study\vue\primevue\vueSvg...
│
└ 项目初始化完成,可执行以下命令:
cd vueSvg
pnpm install
pnpm format
pnpm dev
| 可选:使用以下命令在项目目录中初始化 Git:
git init && git add -A && git commit -m "initial commit"
空的 vue 项目创建好后,开始安装 vite-plugin-svg-icons
安装配置 vite-plugin-svg-icons
安装
pnpm add -D vite-plugin-svg-icons
在 vite.config.ts 中配置。
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
plugins: [
……
createSvgIconsPlugin({
iconDirs: [fileURLToPath(new URL('./src/icons', import.meta.url))],
symbolId: 'icon-[dir]-[name]',
}),
]
在 ./src/main.ts 中添加。
import 'virtual:svg-icons-register'
新建组件 ./src/components/SvgIcon/SvgIcon.vue
<template>
<svg :width="width" :height="height" aria-hidden="true">
<use :href="symbolId" :fill="color" />
</svg>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
interface Props {
prefix?: string
name: string
color?: string
width?: string
height?: string
}
const props = withDefaults(defineProps<Props>(), {
prefix: 'icon',
name: '',
color: '#333',
width: '20px',
height: '20px',
})
const symbolId = computed(() => {
return `#${props.prefix}-${props.name}`
})
</script>
再安装一个自动导入组件的插件(非必须)
pnpm add -D unplugin-vue-components
# 配置 vite.config.ts
import Components from 'unplugin-vue-components/vite'
plugins: [
……,
Components({
dirs: ['src/components'],
extensions: ['vue'],
deep: true,
dts: true
}),
]
去 https://www.iconfont.cn/ 上下载几个 svg 试试。具体点就从 https://www.iconfont.cn/illustrations/detail?spm=a313x.home_2025.i1.68.260f3a81Iah7ae&cid=52616 下载几只舔狗试试。
这里就下载了两个,分别叫 dog-1.svg,dog-2.svg,将这两个文件放到 ./src/icons/ 目录下。
在 App.vue 中添加测试代码。
<div>
<SvgIcon name="dog-1" width="120px" height="120px" />
<SvgIcon name="dog-2" width="120px" height="120px" />
</div>
运行 pnpm dev 看看效果。

搞个假的 loading
https://www.npmjs.com/package/vite-plugin-app-loading
<template>
<h1>You did it!</h1>
<p>
Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the
documentation
</p>
<div>
<SvgIcon name="dog-1" color="#000" width="120px" height="120px" />
<SvgIcon name="dog-2" color="#000" width="120px" height="120px" />
</div>
<div class="loading" id="__app-loading__">
<div class="loader"></div>
<div class="title">Loading …</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => {
setTimeout(() => {
document.getElementById('__app-loading__')?.remove()
}, 1000)
})
</script>
<style scoped>
html {
line-height: 1.15;
}
.loading {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #f4f7f9;
transition: all 0.8s ease-out;
}
.loading.hidden {
pointer-events: none;
visibility: hidden;
opacity: 0;
transition: all 0.8s ease-out;
}
.dark .loading {
background: #0d0d10;
}
.title {
margin-top: 66px;
font-size: 28px;
font-weight: 600;
color: rgb(0 0 0 / 85%);
}
.dark .title {
color: #fff;
}
.loader {
position: relative;
width: 48px;
height: 48px;
}
.loader::before {
position: absolute;
top: 60px;
left: 0;
width: 48px;
height: 5px;
content: '';
background: hsl(var(--primary, 85 100% 50%) / 50%);
border-radius: 50%;
animation: shadow-ani 0.5s linear infinite;
}
.loader::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
background: hsl(var(--primary, 98 100% 50%));
border-radius: 4px;
animation: jump-ani 0.5s linear infinite;
}
@keyframes jump-ani {
15% {
border-bottom-right-radius: 3px;
}
25% {
transform: translateY(9px) rotate(22.5deg);
}
50% {
border-bottom-right-radius: 40px;
transform: translateY(18px) scale(1, 0.9) rotate(45deg);
}
75% {
transform: translateY(9px) rotate(67.5deg);
}
100% {
transform: translateY(0) rotate(90deg);
}
}
@keyframes shadow-ani {
0%,
100% {
transform: scale(1, 1);
}
50% {
transform: scale(1.2, 1);
}
}
</style>