1. 安装 svg-sprite-loader
npm i svg-sprite-loader --save-dev
2. SvgIcon component
<script setup>
import {computed, useCssModule} from "vue";
const props = defineProps({
name: {
type: String,
required: true
}
})
const styles = useCssModule()
const iconName = computed(() => `#icon-${props.name}`);
const svgClass = computed(() => {
const className = [styles['svg-icon']]
if (props.name) className.push(`icon-${props.name}`)
return className
})
</script>
<template>
<svg :class="svgClass" v-bind="$attrs">
<use :xlink:href="iconName"></use>
</svg>
</template>
<style module="">
.svg-icon {
1em;
height: 1em;
fill: currentColor;
vertical-align: middle;
overflow: hidden;
}
</style>
import svgIcon from './icon'
export default {
install: Vue => Vue.component('svg-icon', svgIcon)
}
3. 新建svgBuilder.js
import {readFileSync, readdirSync} from 'fs'
import path from 'path'
let idPrefix = ''
const svgTitle = /<svg([^>+].*?)>/
const clearHeightWidth = /(width|height)="([^>+].*?)"/g
const hasViewBox = /(viewBox="[^>+].*?")/g
const clearReturn = /(
)|(
)/g
const findSvgFile = (dir) => {
const svgRes = []
const directory = readdirSync(dir, {withFileTypes: true})
for (const dirent of directory) {
if (dirent?.isDirectory()) {
svgRes.push(...findSvgFile(path.join(dir, dirent.name, '/')))
} else {
const svg = readFileSync(path.join(dir, dirent.name))
.toString()
.replace(clearReturn, '')
.replace(svgTitle, ($1, $2) => {
let width = 0
let height = 0
let content = $2.replace(
clearHeightWidth,
(s1, s2, s3) => {
if (s2 === 'width') {
width = s3
} else if (s2 === 'height') {
height = s3
}
return ''
}
)
if (!hasViewBox.test($2)) {
content += `viewBox="0 0 ${width} ${height}"`
}
return `<symbol id="${idPrefix}-${dirent.name.replace(
'.svg',
''
)}" ${content}>`
})
.replace('</svg>', '</symbol>')
svgRes.push(svg)
}
}
return svgRes
}
const svgBuilder = (path, prefix = 'icon') => {
if (!path) return
idPrefix = prefix
const res = findSvgFile(path)
return {
name: 'svg-transform',
transformIndexHtml(html) {
return html.replace(
'<body>',
`<body>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="position: absolute; 0; height: 0">
${res.join('')}
</svg>`
)
}
}
}
export default svgBuilder
4. main.js 中全局注册
// ...
import svgIcon from '@/components/svgIcon'
// ...
const app = createApp(App)
app.use(svgIcon)
5. src目录下新建icons
文件夹内存放svg图标
6. vite.config.js 中
import svgBuilder from './plugins/svgBuilder'
// ...
plugins: [
// ...
svgBuilder('./src/icons')
]
7. 使用
<!-- name 为 svg 的文件名 -->
<svg-icon name="right">
</svg([^>