开发中经常使用图标,通过unplugin-icons 插件我们可以在项目中自动下载所需的图标,但实际开发中我们还需要iconfont以及项目ui切图中的图标,这就需要使用自定义SvgIcon组件。具体操作步骤
一、安装包
npm i -D vite-plugin-svg-icons unplugin-icons unocss
二、自定义组件SvgIcon
<script setup lang="ts" name="SvgIcon">
import type {CSSProperties} from 'vue'
const props = defineProps({
name: {
type: String,
required: true,
},
color: {
type: String,
default: 'currentColor',
},
size: {
type: [Number, String],
default: 16,
},
spin: {
type: Boolean,
default: false,
},
})
const symbolId = computed(() => `#${props.name}`)
// 判断是否是自定义图标
const isIcon = computed(() => props.name?.startsWith('icon'))
const getStyle = computed((): CSSProperties => {
const {size} = props
let s = `${size}`
s = `${s.replace('px', '')}px`
return {fontSize: s,}
})
</script>
<template>
<i :class="['el-icon', spin && 'svg-icon-spin']" :style="getStyle">
<svg v-if="isIcon" aria-hidden="true">
<use :xlink:href="symbolId" rel="external nofollow" :fill="color"/>
</svg>
<span v-else :class="name"/>
</i>
</template>
<style scoped lang="scss">
.el-icon {
svg {
width: 1em;
height: 1em;
}
}
.svg-icon-spin {
animation: circle 1.5s infinite linear;
}
/* 旋转动画 */
@keyframes circle {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
</style>
三、配置
vite.config.ts配置
import vue from '@vitejs/plugin-vue';
import {resolve} from 'path';
import {defineConfig, loadEnv, ConfigEnv} from 'vite';
// 这里获取element plus ant-design 中的图标数据对象
// 在unocss 配置 就可以通过i-ep-图标名称 类名访问element plus 图标
// 通过i-ant-design-图标名称访问 ant-design 图标
// @iconify-json/ep @iconify-json/ant-design 自已安装或者在页面使用<i-ep-edit /> 图标 自动下载
import {icons as ele} from '@iconify-json/ep'
import {icons as ant} from '@iconify-json/ant-design'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import {createSvgIconsPlugin} from "vite-plugin-svg-icons";
import UnoCSS from 'unocss/vite'
const pathResolve = (dir: string) => {
return resolve(__dirname, '.', dir);
};
const viteConfig = defineConfig((mode: ConfigEnv) => {
const env = loadEnv(mode.mode, process.cwd());
return {
plugins: [vue(),
Icons({autoInstall: true, compiler: 'vue3'}),
// 自定义图标配置
createSvgIconsPlugin({
// 指定要缓存的文件夹
// eslint-disable-next-line no-undef
iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
// 指定symbolId格式
symbolId: 'icon-[name]',
//svgo额外配置,具体配置参考https://github.com/svg/svgo
svgoOptions: {
plugins: [
{
name: 'removeAttrs',
params: {attrs: ['class', 'data-name', 'fill', 'stroke']}
}
]
}
}),
UnoCSS({
safelist: [...Object.keys(ele.icons).map(name => `i-${ele.prefix}-${name}`),
...Object.keys(ant.icons).map(name => `i-${ant.prefix}-${name}`),
],// 引入
// 以下配置是为了可以直接使用标签 <i-ep-edit />
variants: [
{
match: (s) => {
if (s.startsWith('i-')) {
return {
matcher: s,
selector: (s) => {
return s.startsWith('.') ? `${s.slice(1)},${s}` : s
},
}
}
},
},
],
}),
root: process.cwd(),
resolve: { '/@': pathResolve('./src/')},
});
export default viteConfig;
unocss.config.ts配置
import { defineConfig, presetAttributify, presetIcons, presetUno } from 'unocss'
export default defineConfig({
presets: [presetAttributify(), presetIcons(), presetUno()],
})
main.ts配置
import {createApp} from 'vue';
import App from './App.vue';
import 'uno.css'
import 'virtual:svg-icons-register'
import SvgIcon from "/@/components/SvgIcon.vue";
const app = createApp(App);
// 注册全局
app.component('SvgIcon', SvgIcon)
app.mount('#app');
四、使用
自定义图标只要下载svg 文件到 assets/icons 文件夹下,自定义图标 通过icon-图标名称访问,iconify图标通过i-图标来源-图标名称访问 i-ep-edit i-ant-design-user