Skip to content

Commit 1135b43

Browse files
committed
新增SvgIcon组件
1 parent 0d6673e commit 1135b43

File tree

10 files changed

+1112
-3
lines changed

10 files changed

+1112
-3
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@vitejs/plugin-vue": "^2.3.1",
2121
"sass": "^1.50.0",
2222
"sass-loader": "^12.6.0",
23+
"svg-sprite-loader": "^6.0.11",
2324
"vite": "^2.9.1",
2425
"vite-plugin-style-import": "1.4.1"
2526
}

src/assets/icons/svg/Friend.svg

Lines changed: 2 additions & 0 deletions
Loading

src/assets/icons/svg/Order.svg

Lines changed: 2 additions & 0 deletions
Loading

src/assets/icons/svg/Profit.svg

Lines changed: 2 additions & 0 deletions
Loading

src/assets/icons/svg/Withdrawal.svg

Lines changed: 2 additions & 0 deletions
Loading

src/components/SvgIcon/index.vue

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<template>
2+
<svg :class="svgClass" v-bind="$attrs" :style="{ color: color, width: width, height: height }">
3+
<use :xlink:href="iconName" />
4+
</svg>
5+
</template>
6+
7+
<script setup>
8+
import { computed } from "vue";
9+
10+
const props = defineProps({
11+
name: {
12+
type: String,
13+
required: true
14+
},
15+
color: {
16+
type: String,
17+
default: ''
18+
},
19+
width: {
20+
type: String,
21+
default: '1.5em'
22+
},
23+
height: {
24+
type: String,
25+
default: '1.5em'
26+
}
27+
})
28+
29+
const iconName = computed(() => `#icon-${props.name}`);
30+
const svgClass = computed(() => {
31+
console.log(props.name, 'props.name');
32+
if (props.name) {
33+
return `svg-icon icon-${props.name}`
34+
}
35+
return 'svg-icon'
36+
});
37+
</script>
38+
39+
<style lang='scss'>
40+
.svg-icon {
41+
fill: currentColor;
42+
vertical-align: middle;
43+
}
44+
</style>

src/main.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { createPinia } from 'pinia'
44
import App from './App.vue'
55
import router from './router'
66

7+
import svgIcon from '@/components/SvgIcon/index.vue'
8+
79
import 'amfe-flexible/index.js'
810
import './assets/styles/index.scss'
911

@@ -14,4 +16,6 @@ const app = createApp(App)
1416
app.use(createPinia())
1517
app.use(router)
1618

19+
app.component('svg-icon', svgIcon)
20+
1721
app.mount('#app')

src/plugins/svgBuilder.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { readFileSync, readdirSync } from 'fs'
2+
3+
let idPerfix = ''
4+
const svgTitle = /<svg([^>+].*?)>/
5+
const clearHeightWidth = /(width|height)="([^>+].*?)"/g
6+
7+
const hasViewBox = /(viewBox="[^>+].*?")/g
8+
9+
const clearReturn = /(\r)|(\n)/g
10+
11+
function findSvgFile(dir) {
12+
const svgRes = []
13+
const dirents = readdirSync(dir, {
14+
withFileTypes: true
15+
})
16+
for (const dirent of dirents) {
17+
if (dirent.isDirectory()) {
18+
svgRes.push(...findSvgFile(dir + dirent.name + '/'))
19+
} else {
20+
const svg = readFileSync(dir + dirent.name)
21+
.toString()
22+
.replace(clearReturn, '')
23+
.replace(svgTitle, ($1, $2) => {
24+
// console.log(++i)
25+
// console.log(dirent.name)
26+
let width = 0
27+
let height = 0
28+
let content = $2.replace(
29+
clearHeightWidth,
30+
(s1, s2, s3) => {
31+
if (s2 === 'width') {
32+
width = s3
33+
} else if (s2 === 'height') {
34+
height = s3
35+
}
36+
return ''
37+
}
38+
)
39+
if (!hasViewBox.test($2)) {
40+
content += `viewBox="0 0 ${width} ${height}"`
41+
}
42+
return `<symbol id="${idPerfix}-${dirent.name.replace(
43+
'.svg',
44+
''
45+
)}" ${content}>`
46+
})
47+
.replace('</svg>', '</symbol>')
48+
svgRes.push(svg)
49+
}
50+
}
51+
return svgRes
52+
}
53+
54+
export const svgBuilder = (path, perfix = 'icon') => {
55+
if (path === '') return
56+
idPerfix = perfix
57+
const res = findSvgFile(path)
58+
// console.log(res.length)
59+
// const res = []
60+
return {
61+
name: 'svg-transform',
62+
transformIndexHtml(html) {
63+
return html.replace(
64+
'<body>',
65+
`
66+
<body>
67+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
68+
${res.join('')}
69+
</svg>
70+
`
71+
)
72+
}
73+
}
74+
}

vite.config.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ import { fileURLToPath, URL } from 'url'
22
import styleImport, { VantResolve } from 'vite-plugin-style-import';
33
import { defineConfig } from 'vite'
44
import vue from '@vitejs/plugin-vue'
5+
import { svgBuilder } from './src/plugins/svgBuilder';
56

67
// https://vitejs.dev/config/
78
export default defineConfig({
8-
plugins: [vue(), styleImport({
9-
resolves: [VantResolve()],
10-
})],
9+
plugins: [
10+
vue(),
11+
styleImport({
12+
resolves: [VantResolve()],
13+
}),
14+
svgBuilder('./src/assets/icons/svg/')
15+
],
1116
resolve: {
1217
alias: {
1318
'@': fileURLToPath(new URL('./src', import.meta.url))

0 commit comments

Comments
 (0)