原理
原理就是通过插件 雪碧图生成插件vite-plugin-svg-icons把指定目录下的svg图片整合打包成一整个svg雪碧图,然后插件会把把整个雪碧图插入到html中,然后引入的时候通过id去调用svg,如下图。
不废话直接上代码
文件路径
vite.config.ts
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { resolve } from 'node:path'
import AutoImport from 'unplugin-auto-import/vite'
import Unocss from 'unocss/vite'
export default defineConfig({
base: './',
plugins: [
AutoImport({
imports: ['vue', 'uni-app'],
dts: './src/dts/auto-imports.d.ts',
eslintrc: {
enabled: true
}
}),
uni(),
Unocss(),
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), 'src/assets/svgs')], // icon存放的目录
symbolId: 'icon-[name]', // symbol的id
inject: 'body-last', // 插入的位置
customDomId: '__svg__icons__dom__' // svg的id
})
],
server: {
port: 8080
},
resolve: {
alias: {
'@': `${resolve(__dirname)}/`
}
},
build: {
// uno报错处理
watch: {
exclude: ['node_modules/**', '/__uno.css']
}
}
})
SvgIcon.vue(写个SvgIcon组件统一引入)
<template>
<svg class="svg-icon" :style="iconStyle" aria-hidden="true">
<use :xlink:href="symbolId" :fill="color" />
</svg>
</template>
<script setup lang="ts" name="SvgIcon">
import { computed, CSSProperties } from 'vue'
interface SvgProps {
name: string // 图标的名称 ==> 必传
prefix?: string // 图标的前缀 ==> 非必传(默认为"icon")
iconStyle?: CSSProperties // 图标的样式 ==> 非必传
color?: string // 填充颜色
}
const props = withDefaults(defineProps<SvgProps>(), {
prefix: 'icon',
color: ''
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>
<style scoped>
.svg-icon {
display: inline-block;
width: 1em;
height: 1em;
overflow: hidden;
vertical-align: -0.15em; /* 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果 */
outline: none;
fill: currentcolor; /* 定义元素的颜色,currentColor是一个变量,这个变量的值就表示当前元素的color值,如果当前元素未设置color值,则从父元素继承 */
}
</style>
使用SvgIcon.vue
// main.ts
// 每个人的项目可能都不一样,只看引入SvgIcon的部分就行
import { createSSRApp } from 'vue'
import App from './App.vue'
import setupStore from './store'
import SvgIcon from './components/SvgIcon'
import 'virtual:uno.css'
import 'virtual:svg-icons-register'
export function createApp() {
const app = createSSRApp(App)
app.component('SvgIcon', SvgIcon)
setupStore(app)
return {
app
}
}
// test.vue
// name为对应文件名
<SvgIcon
class="mr-10rpx"
:style="{ width: '40rpx', height: '40rpx' }"
:color="stateIndexRef > 0 ? '#fff' : '#999'"
name="undo"
@click="handlePre"
/>