背景
日前,开发一个配置数据表单类的框架,需要考虑框架的扩展性,以及使用的便捷性,其中图标类如何便捷的引入也在考虑之中。
期望实现的效果是在新增一个svg时,仅将svg文件存放到某一个文件夹下,之后使用时通过类似于<mis-icon icon="name">
这种方式即可使用。
思路
- 全局注册组件
- 使用js读取文件夹下的所有svg导入至项目中
实现
全局注册组件
在src/compoments
下创建MisIcon.vue
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"/>
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
icon: {
type: String,
required: true,
},
className: {
type: String,
default: '',
},
},
computed: {
iconName () {
return `#icon-${this.icon}`
},
svgClass () {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
},
}
</script>
<style scoped>
.svg-icon {
1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
集中存放svg文件
-
在
src/assets/svg
文件夹下存放所有svg文件注意:如果需要修改svg的颜色,svg文件中的填充色
fill
必须删除 -
在
src/assets
下创建svg.js
文件// 读取所有svg文件 const requireAll = requireContext => requireContext.keys().map(requireContext) const req = require.context('/src/assets/svg', false, /.svg$/) requireAll(req)
全局注册组件并导入svg
// main.js
import '@/assets/svg.js'
import MisIcon from '@/components/MisIcon.vue' // svg组件
// 注册全局插件
Vue.component('mis-icon', MisIcon)
重要的一步 - 配置loader
根目录下的vue.config.js
文件中
const path = require('path')
function resolve(dir) {
return path.join(__dirname, './', dir)
}
module.exports = {
chainWebpack: config => {
// svg 规则
const svgRule = config.module.rule('svg') // 找到原有的svg-loader
svgRule.uses.clear() // 清除已有的loader, 如果不清除会在原有loader之后再使用当前loader规则
svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
svgRule // 添加svg新的loader处理
.test(/.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]',
})
// 修改images loader,添加svg处理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('src/assets/svg'))
config.module
.rule('images')
.test(/.(png|jpe?g|gif|svg)(?.*)?$/)
}
}
使用
<template>
<div>
<!-- icon的值为svg文件名 -->
<mis-icon icon="test" className="test-icon"></mis-icon>
</div>
</template>
<script>
export default {
name: 'SvgTest'
}
</script>
<style scoped>
.test-icon{
color: blue;
200px;
height: 200px;
&:hover{
color: lightblue;
}
}
</style>