前言
最近在做项目的优化升级,因为折腾了一下午的图标管理,所以就把自己的经验分享出来,希望可以帮助大家更快的解决自己的需求。
我现在的项目,都是引入iconfont的图标库,真是的好用又方便。现在有三种模式,使用方法可以在官网的 使用说明 页查看。我们今天主要讨论的主要是第三种,也就是svg图标的优化。
简单封装组件
使用说明里有提及,我们引入官方生成的库文件路径。写好css样式,页面代码引用如下:
复制代码
我们简单的做一个组件封装如下:
// SvgIcon.vue
复制代码
将该组件注册为全局组件。新建文件夹,路径为src/icons
。在其中新建一个index.js文件。
// icons/index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon.vue'
Vue.component('svg-icon', SvgIcon)
复制代码
在main.js
中,我们引入这个index.js
import './icons/index.js'
复制代码
这样我们就可以在文件中随意使用svg-icon
组件了。
使用svg-sprite-loader
现在我们的svg文件是整体的,每当我们修改的时候,需要在iconfont上生成新的整体文件。那么是否能需要用一个icon的时候,就自己手动加一个呢?然后自动打包成一个整体文件。webpack可以帮我们实现。
首先,我们新建一个文件夹专门来放置单个svg文件。
如图,引入了多个从iconfont中下载的彩色图标svg文件。我们使用svg-sprite-loader
来把所有的单个svg合成为整体的svg雪碧文件。可以先看vue-cli3中的关于svg的默认配置(通过
vue inspect
命令查看,也可以在
vue ui
的界面中点击查看):
/* config.module.rule('svg') */
{
"test": /\.(svg)(\?.*)?$/,
"use": [
{
"loader": "file-loader",
"options": {
"name": "img/[name].[hash:8].[ext]"
}
}
]
},
复制代码
现在我们在vue.config.js
文件中,来改写一下这个配置。
chainWebpack: config => {
// 我们先删除原有的svg rule。
config.module.rules.delete('svg')
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 但我们有的svg可能并不都是图标。我们的需要对icons/svg以外的svg文件做处理。我们把images的rule添加上svg格式。
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('src/icons'))
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/)
}
复制代码
现在我们只要import进这个svg文件就可以使用了。
import "@/icons/sun.svg";
// 使用
复制代码
自动导入webpack的require.context
上面示例中我们是手动import
一个图标,但一旦图标多起来,手动操作就太不优雅了。我们可以使用webpack自带的require.context
功能来实现自动导入功能。
// icons/index.js
//(创建出)一个 context,其中文件来自 svg 目录,不包含子目录,request 以 `.svg` 结尾。
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
复制代码
图标再多,都可以毫无烦恼啦~~~
进一步压缩 svgo-loader
其实我们引入的单个svg文件中有很多无用的信息。
svg-sprite-loader
也做了相关处理,但是它只提取到
path
标签整体,如果path路径内包含的无用的注释信息,如:
依旧存在。
我们可以使用 svgo-loader
来进一步精简svg的内容。删除掉path
标签内的注释信息。配置如下:
// vue.config.js
chainWebpack: config => {
config.module.rules.delete('svg')
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
.use('svgo-loader')
.loader('svgo-loader')
.end()
}
复制代码
好了,这里就是所有关于svg图标使用和优化的全部内容了。如果有更好的方案和问题,欢迎大家指出和分享。
参考资料
- webpackg官网-管理依赖
- iconfont-使用说明
- 手摸手,带你优雅的使用 icon