Vue3使用本地svg渲染icon
原创2022年3月1日
1.安装vite-plugin-svg-icons
pnpm i vite-plugin-svg-icons -D
2.将本地svg文件放入/src/assets/icons/*.svg中
3. 编写svg-icon plugin
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default function createSvgIcon(isBuild) {
return createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/')],
symbolId: 'icon-[dir]-[name]',
svgoOptions: isBuild
})
}
4.配置vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import createSvgIcon from "./src/plugins/svg-icon";
// https://vitejs.dev/config/
export default ({ mode, command }) => {
return defineConfig({
plugins: [
vue(),
createSvgIcon(command === 'build'), // add
……
]
})
}
5.main.js中引入脚本
import { createApp } from 'vue'
import App from './App.vue'
import 'virtual:svg-icons-register'; // add
createApp(App).mount('#app')
6.编写SvgIcon组件
<script setup name="SvgIcon">
import {computed} from "vue"
const props = defineProps({
name: {
type: String,
required: true
},
flip: {
type: String,
validator(value) {
return ['', 'horizontal', 'vertical', 'both'].includes(value)
},
default: ''
},
rotate: {
type: Number,
validator(value) {
return value >= 0 && value <= 360
},
default: 0
}
})
const transformStyle = computed(() => {
let style = []
if (props.flip !== '') {
switch (props.flip) {
case 'horizontal':
style.push('rotateY(180deg)')
break
case 'vertical':
style.push('rotateX(180deg)')
break
case 'both':
style.push('rotateX(180deg)')
style.push('rotateY(180deg)')
break
}
}
if (props.rotate !== 0) {
style.push(`rotate(${props.rotate}deg)`)
}
return `transform: ${style.join(' ')};`
})
</script>
<template>
<svg class="svg-icon" :style="transformStyle" aria-hidden="true">
<use :xlink:href="`#icon-${name}`" />
</svg>
</template>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentcolor;
overflow: hidden;
}
</style>
7.使用
<script setup>
import SvgIcon from './components/SvgIcon.vue'
</script>
<template>
// 此处name即本地svg文件名
<svg-icon name="search-down" />
</template>
Loading...