1.创建目录
icons文件下放所有后缀为svg的图标
2.下载依赖
下载依赖`svgo-loader`和`svg-sprite-loader`
npm install svg-sprite-loader --save-dev
npm install svgo-loader --save-dev
`svgo-loader`用于优化、压缩和处理SVG文件,而`svg-sprite-loader`用于将多个独立的SVG图标文件合并为一个SVG精灵文件,并提供在应用中引用和使用这些图标的便利性。 结合使用,以实现最佳的SVG图标集成和优化。
3.配置vue.config.js
const { join } = require('path')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
chainWebpack: config => {
/* 跳过 babel-loader */
config.module.rule('js').exclude.add(path => {
return /[\\/]src[\\/]libs[\\/].+\.js$/.test(path)
})
const svgSpriteIconsDir = join(__dirname, './src/components/SvgIcon/icons/')
config.module.rule('svg').exclude.add(svgSpriteIconsDir)
config.module
.rule('svg-sprite')
.after('svg')
.test(/\.(svg)(\?.*)?$/)
.include.add(svgSpriteIconsDir)
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({ symbolId: 'svgSpriteIcon__[name]' })
.end()
.use('svgo-loader')
.loader('svgo-loader')
},
})
4.创建index.js 导入所有`svg`图标
<!-- svg-sprite 图标 -->
<!-- 单色模式(非'mt-'前缀),大小继承至 font-size,颜色继承至 color -->
<!-- 多色模式('mt-'前缀),大小继承至 font-size,颜色则原始显示 -->
<!-- require.context 方法是 Webpack 提供的一个特殊方法,它接受三个参数:
1.要搜索的目录的相对路径(或绝对路径)。
2.是否搜索子文件夹。如果为 true,则递归搜索子文件夹;如果为 false,则只搜索第一层目录。
3.一个正则表达式,用于匹配文件名。
通过调用 require.context 方法并传入上述参数,你可以创建一个上下文模块。这个上下文模块拥有一些特殊方法和属性,包括 keys 方法和 resolve 方法。
keys 方法是一个函数,返回上下文模块中所有匹配的文件的相对路径字符串组成的数组。
resolve 方法是一个函数,接受一个路径参数,并返回该路径在上下文模块中的模块 ID。
-->
<script>
let requireCtx
try {
requireCtx = require.context(
'./icons/',
false, // 不解析子文件夹
/\.svg$/,
)
} catch (err) {
if (
/* 允许文件夹缺失(处理 git 无法提交空文件夹的情况) */
err.code === 'MODULE_NOT_FOUND'
) {
requireCtx = () => {}
requireCtx.keys = () => []
} else {
throw err
}
}
const fileNames = requireCtx.keys()
const names = Object.freeze(
fileNames.map(fileName => //取出没有后缀的文件名
fileName
.split(/[/\\]+/)
.pop() //pop() ,移除并返回数组的最后一个元素。
.replace(/\.\w+$/, ''), // /\.\w+$/ 匹配以点号后跟一个或多个字母、数字或下划线结尾的字符串。. 匹配任意字符(除了换行符),而 \w 匹配任意字母、数字或下划线字符。+ 是一个量词,表示匹配前面的模式一次或多次。$ 是一个锚点,表示匹配字符串的结尾。
),
)
fileNames.forEach(fileName => requireCtx(fileName))
export { names }
export default {
name: 'SvgIcon',
props: {
icon: {
type: String,
required: true,
},
},
}
</script>
<template>
<i :class="['svg-icon', `svg-icon-${icon}`]">
<svg class="svg-icon__icon">
<use :xlink:href="`#svgSpriteIcon__${icon}`" />
</svg>
</i>
</template>
<style lang="less">
.svg-icon {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -0.165em;
font-style: normal;
line-height: 1;
&__icon {
display: block;
overflow: hidden;
width: 100%;
height: 100%;
fill: currentColor;
}
}
[id^='svgSpriteIcon__']:not([id^='svgSpriteIcon__mt-']) {
// svgo-loader 会自动计算内联样式并应用到 fill 属性上
[fill]:not([fill='none']):not([fill='transparent']) {
fill: currentColor;
}
// svgo-loader 会自动计算内联样式并应用到 stroke 属性上
[stroke]:not([stroke='none']):not([stroke='transparent']) {
stroke: currentColor;
}
}
</style>
5.全局注册组件
可创建一个装全局的js文件
index.js的代码为:
/**
* !!!慎用全局注册
* 这里只适合注册,具体实现需拆分到单独的文件
*/
import Vue from 'vue'
const SvgIcon = function() {
return import(/* webpackChunkName: "low-priority" */ '@/components/SvgIcon/index.vue')
}
/* 全局组件 Vue.component */
Vue.component('svg-icon', SvgIcon)
6.引入全局文件
在main.js中引入全局文件
7.使用
icon名称一定要对应!
可单独设置类名来控制svg的颜色和大小