- 安装解析svg类型图标的依赖
npm install svg-sprite-loader --save-dev
npm install svgo --save-dev // 一个用于优化SVG文件的Node.js工具
很多网上下载或者导出的SVG文件中会有很多冗余无用的信息,可以通过svgo插件对它进行优化。无用的信息有:编辑器源信息,注释,以及其它一些不会影响渲染效果但可以去除的信息等。该svgo具有基于插件的体系结构,因此几乎每个优化都是一个单独的插件。
- 在
src
目录下新建src/icons/svg
目录,存放项目所使用的所有图标svg
文件
- 在
vue-config.js
中添加配置:
module.exports = {
chainWebpack(config) {
//配置svg
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons')) //处理svg目录(根据你建的文件路径)
// .include.add(resolve('src/icons')).add(resolve('src/assets'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
},
// .include.add(resolve('src/icons')).add(resolve('src/assets'))
配置中这行代码是用来处理包含svg文件的目录,我在原基础上添加了asset文件夹
所以如果想正常直接使用svg文件,需要将其放置在除了'src/icons'、'src/assets'下的其他目录
然后在代码直接引入即可
<img src='./attack_chain_icon1.svg'>
- 创建组件
components/SvgIcon.vue
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" ></div>
<svg v-else :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
import { isExternal } from '@/utils/validate'
import '@/icons'
export default {
name: 'svg-icon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
/* width: 1rem;
height: 1rem; */
vertical-align: middle;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>
isExternal方法及作用
/**校验传入的iconClass是否为外部链接
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path);
}
- 在
src/icons
目录下新建index.js
文件、svgo.yml
文件
index.js中
import Vue from 'vue';
import SvgIcon from '@/components/SvgIcon'; // svg component
// register globally
Vue.component('svg-icon', SvgIcon);
const requireAll = requireContext => requireContext.keys().map(requireContext);
const req = require.context('./svg', false, /\.svg$/);
requireAll(req);
如果项目图标文件较多,可以对 icons
目录做详细的划分,然后修改上述 index.js
svgo.yml中(基于svgo对svg文件进行压缩)
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'
配置package.json文件
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
当初始化使用或者新增svg图标时,需要执行以下代码
npm run svgo
- 在
main.js
入口文件中 全局引入icons
。
import "./icons";
- 使用svg组件
<svg-icon icon-class="svgName" class="icon" />
//svgName为.svg后缀前的文件名
实际开发中应用场景如:
<div v-for="item in attackChainList" :key="item.stage" class="chain-item">
<svg-icon :icon-class="item.icon" alt="" class="attack-chain" />
<div>{{ item.stage }}</div>
</div>
attackChainList: [
{ icon: 'attack_chain_icon1', stage: '观察' },
{ icon: 'attack_chain_icon2', stage: '实践' },
{ icon: 'attack_chain_icon3', stage: '总结' }
]
.attack-chain {
width: 82px;
height: 77px;
margin-right: 12px;
}