背景
日前,開發一個配置數據表單類的框架,需要考慮框架的擴展性,以及使用的便捷性,其中圖標類如何便捷的引入也在考慮之中。
期望實現的效果是在新增一個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 {
width: 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;
width: 200px;
height: 200px;
&:hover{
color: lightblue;
}
}
</style>
