- 以下有Vue3、Vue2
Vue3 ts
插件 vite-plugin-svg-icons
vite.config.ts
import path from 'path'
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
import legacy from '@vitejs/plugin-legacy'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, './')
return {
base: env.VITE_BASE_URL,
plugins: [
vue(),
vueJsx(),
Components({
resolvers: [
AntDesignVueResolver({
importStyle: 'less' // css in js
})
],
version: 3
}),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
symbolId: 'icon-[dir]-[name]'
}),
legacy({
targets: ['ie > 11'],
additionalLegacyPolyfills: ['regenerator-runtime/runtime']
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
lodash: 'lodash-es'
}
},
server: {
host: '0.0.0.0',
port: 3000,
cors: true,
proxy: {
'/dev/api': {
target: 'http://10.10.22.133:8580',
// target: 'http://10.10.25.71',
// target: 'http://10.10.25.83',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/dev\/api/, '')
}
},
hmr: { overlay: false }
},
build: {
outDir: env.VITE_OUT_DIR,
assetsDir: 'assets',
}
}
})
svg-icon.vue
import 'virtual:svg-icons-register';
<template>
<svg aria-hidden="true" class="svg-icon" :style="style" v-bind="$attrs">
<use :href="symbolId" :fill="color || '#333'" />
</svg>
</template>
<script setup lang="ts">
import { isNumber } from 'lodash-es'
import { computed } from 'vue'
import px2rem from '@/utils/flexble'
const props = defineProps<{
prefix?: string
name: string
color?: string
size?: number | [number, number]
}>()
const symbolId = computed(() => `#${props.prefix || 'icon'}-${props.name}`)
const width = computed(() => {
if (!props.size) return ''
return isNumber(props.size) ? props.size : props.size[0]
})
const height = computed(() => {
if (!props.size) return ''
return isNumber(props.size) ? props.size : props.size[1]
})
const style = computed(() => {
const style: { width?: string; height?: string } = {}
if (width.value) style.width = px2rem(width.value) as string
if (height.value) style.height = px2rem(height.value) as string
return style
})
</script>
vue2
svg-icon.js
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon/index.vue"; // svg component
// register globally
Vue.component("svg-icon", SvgIcon);
// 在svg-icon.js同层文件夹svg下引入svg图片
const req = require.context("./svg", true, /\.svg$/);
const requireAll = (requireContext) =>
requireContext.keys().map(requireContext);
requireAll(req);
SvgIcon/index.vue
<template>
<div
v-if="isExternal"
:style="styleExternalIcon"
class="svg-external-icon svg-icon"
v-on="$listeners"
/>
<svg
v-else
:class="svgClass"
aria-hidden="true"
:style="styles"
v-bind="$attrs"
v-on="$listeners"
>
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path);
}
export default {
name: "SvgIcon",
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ""
},
size: {
type: Number,
default: 0
},
rotate: {
type: Number,
default: 0
}
},
computed: {
isExternal() {
return isExternal(this.iconClass);
},
iconName() {
return `#icon-${this.iconClass}`;
},
svgClass() {
if (this.className) {
return `svg-icon ${this.className}`;
}
return "svg-icon";
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
"-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`
};
},
styles() {
let css = {};
if (this.size) {
css = {
...css,
width: `${this.size}px`,
height: `${this.size}px`
};
}
if (this.rotate) {
css = {
...css,
transform: `rotate(${this.rotate}deg)`
};
}
return css;
}
}
};
</script>
<style scoped>
.svg-icon {
width: 16px;
height: 16px;
vertical-align: middle;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>