vue3自定义svg图标组件
可参考:
未来必热:SVG Sprites技术介绍
懒人神器:svg-sprite-loader实现自己的Icon组件
在Vue3项目中使用svg-sprite-loader
前置知识
在页面中,虽然可以通过如下的方式使用img标签,来引入svg图标。但是,如果这个路径很长,也是比较麻烦的。
<img src="./svg/icon.svg" />
在svg里面,可以在文档中先定义Symbol,然后svg使用的时候,只须通过标识去引用指定的svg即可,Symbol的放置顺序不一定要在最前面,案例如下:
<html>
<head>
<meta charset="utf-8">
<title>SVG Sprite使用</title>
<style>
li {
font-size: 14px;
margin-top: 5px;
color: #369;
}
.webicon {
width: 16px;
height: 16px;
margin-right: 5px;
vertical-align: -2px;
fill: #369;
}
</style>
</head>
<body>
<div style="display: none;"><svg>
<symbol id="liwu" viewBox="-80 -72.013 160 144.025">
<path
d="M-71.949-16.039h55.974v-55.974h-55.974V-16.039z M16.102-16.039h55.975v-55.974H16.102V-16.039z M-80,32.013h64.025v-40H-80V32.013z M80,32.013v-40H16.102v40H80z M-7.923,32.013H8.051V-72.013H-7.923V32.013z M16.102,39.936 h-32.077v24.025h32.077V39.936z M64.025,39.936h-40l15.719,32.077h24.281V39.936z M-23.898,39.936h-40v32.077H-40L-23.898,39.936z"
transform="matrix(1 0 0 -1 0 0)"></path>
</symbol>
<symbol id="qianbi" viewBox="-79.5 -79.5 159 159">
<path
d="M79.5,32.802l-93.538-93.538l-46.699,46.699L32.802,79.5L79.5,32.802z M-79.5-32.802L-32.802-79.5H-79.5 V-32.802z"
transform="matrix(1 0 0 -1 0 0)"></path>
</symbol>
<symbol id="shangchuan" viewBox="-73.623 -78.055 147.245 156.11">
<path
d="M0.069,32.482L64.48-32.205H36.915v-45.85h-73.83l-0.139,45.85h-27.15L0.069,32.482z M73.623,78.055V59.632 H-73.623v18.423H73.623z"
transform="matrix(1 0 0 -1 0 0)"></path>
</symbol>
</svg></div>
<h3>SVG Sprite使用示意</h3>
<ul>
<li><svg class="webicon">
<use xlink:href="#qianbi"></use>
</svg>编辑信息</li>
<li><svg class="webicon">
<use xlink:href="#liwu"></use>
</svg>兑换礼物</li>
<li><svg class="webicon">
<use xlink:href="#shangchuan"></use>
</svg>上传文件</li>
</ul>
</div>
</body>
</html>
自定义svg图标步骤
1. 创建components/SvgIcon/index.vue
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script setup>
import { defineProps, computed } from 'vue'
const props = defineProps({
icon: {
type: String,
required: true
}
})
const iconName = computed(() => {
return `#icon-${props.icon}`
})
</script>
<style lang="scss" scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
2. 创建icons/index.js,
创建icons/index.js,并创建icons/svg图标所在文件夹,icon的图标就放在这个文件夹中。这里是动态的
import SvgIcon from '@/components/SvgIcon'
const svgRequired = require.context('./svg', false, /\.svg$/)
svgRequired.keys().forEach((item) => svgRequired(item))
export default (app) => {
app.component('svg-icon', SvgIcon)
}
3. main.js中注册SvgIcon组件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//import '@/assets/styles/index.scss'
import '@/assets/styles/border.css'
import '@/assets/styles/reset.css'
import '@/router/permission.js'
// import '@/router/init.js'
import {totalCommon} from '@/sys/mixinFunc.js'
import SvgIcon from '@/icons'
// 国际化中文
import zhCn from 'element-plus/es/locale/lang/zh-cn'
const app = createApp(App)
SvgIcon(app);
app.mixin(totalCommon);
app.use(ElementPlus, {
locale: zhCn,
})
app.use(store)
app.use(router)
app.use(ElementPlus)
app.mount('#app')
4. vite.config.js配置svg-sprite-loader
首先,安装scg-sprite-loader
const webpack = require('webpack');
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
lintOnSave: false,
chainWebpack(config) {
// 设置 svg-sprite-loader
// config 为 webpack 配置对象
// config.module 表示创建一个具名规则,以后用来修改规则
config.module
// 规则
.rule('svg')
// 忽略
.exclude.add(resolve('src/icons'))
// 结束
.end()
// config.module 表示创建一个具名规则,以后用来修改规则
config.module
// 规则
.rule('icons')
// 正则,解析 .svg 格式文件
.test(/\.svg$/)
// 解析的文件
.include.add(resolve('src/icons'))
// 结束
.end()
// 新增了一个解析的loader
.use('svg-sprite-loader')
// 具体的loader
.loader('svg-sprite-loader')
// loader 的配置
.options({
symbolId: 'icon-[name]'
})
// 结束
.end()
config
.plugin('ignore')
.use(
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/)
)
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
}
}