背景
最近几个项目常用到svg图片,往往步骤还不少,每次都要上网查一遍怎么配置,不如自己走一遍,深入理解下,记录下来。
配置步骤
在Vue-CLI中配置svg的icon,可以参照下面的步骤。
- 需要用到雪碧图的loader,解析svg。
npm install svg-sprite-loader --save-dev
- 配置vue.config.js,加入sprite-loader的解析。
module.exports = {
chainWebpack: config => {
// 原svg规则覆盖了所有的svg图标,需要先将自己的svg排除,以应用新的sprite规则
// src/assets/icons是我们将要存放svg的目录
config.module
.rule('svg')
.exclude.add(path.join(__dirname, 'src/assets/icons')) // 排除自定义svg目录
.end()
config.module
.rule('icons') // 新规则
.test(/\.svg$/)
.include.add(path.join(__dirname, 'src/assets/icons')) // 新规则应用于我们存放svg的目录
.end()
.use('svg-sprite-loader') // 用sprite-loader接卸
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
}
}
- 创建全局SvgIcon组件,用于页面显示svg icon。组件位置:
src/components/SvgIcon.vue
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="`#icon-${name}`" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
name: { // svg文件名称
type: String,
required: true
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
- 在main.js中,全局引入SvgIcon组件,以及加载所有的svg图标。
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件
// 1. 全局注册SvgIcon组件
Vue.component('svg-icon', SvgIcon)
// 2. 载入所有svg icon
const requireContext = require.context('./assets/icons', false, /\.svg$/)
requireContext.keys().forEach(requireContext)
- 将svg放入
src/asset/icons
目录下
- 在页面中引用,即大功告成。
<svg-icon name="book" /> <!-- name就是svg图标文件的名称 -->
后记
看了好多篇关于svg的配置,往往拿来主义,直接用,有些不合理的地方也一传十,十传百。
1. 引入svg icon
原版是这样:
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
我看来看去,最后不就是执行这一句么requireContext => requireContext.keys().map(requireContext)
,为什么要拐那么多弯呢?而且最终目的只要把资源require进来就行了,用map也没意义,于是我修改成:
const requireContext = require.context('./assets/icons', false, /\.svg$/)
requireContext.keys().forEach(requireContext)
关于requreiContext
a) require.context()
函数功能为加载多个资源,requreiContext
是require.context()
的返回结果,是一个函数,打印出来的代码是这样:
function webpackContext(req) {
var id = webpackContextResolve(req);
return __webpack_require__(id);
}
这个函数的作用就是根据名称加载资源,返回资源对象,如{default:{...}}
.
b) requreiContext
的原型有3个属性,id、keys、resolve, 后两者为函数。keys返回所有资源的文件名列表,resolve返回资源的相对项目的完整路径。打印原型requreiContext.prototype
得到如下结果:
打印requireContext.keys()
得到如下结果:
2. SvgIcon组件
网上大多文章用的是这个版本:
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
a)发现className
属性和svgClass
完全没必要,引用svg-icon
组件时,直接加class
属性就行,会自动合并,何必画蛇添足。像这样就可以了:
<svg-icon name="book" class="myicon" />
b)iconClass
不好理解,直接取名name
更简洁清晰;计算属性iconName
也是完全没太大必要,毕竟组件定下了,name属性就是不变的。
修改后就变成简洁版本:
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="`#icon-${name}`" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
name: {
type: String,
required: true
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
当然,也许有性能或者其他什么方面的考量,目前我没看出加那些的必要。
3. 获取svg icon
我常去的网站是这个,阿里巴巴矢量图标库,资源很丰富。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!